summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorbp <bp@FreeBSD.org>2001-03-10 05:24:45 +0000
committerbp <bp@FreeBSD.org>2001-03-10 05:24:45 +0000
commitdde32853641c8191e1074cc8a3d9b3ae9facfa27 (patch)
tree3496a4f9320d911a7b3ce90b4c45fe032119f1d2 /sys
parent04dc7092d8850e0118c795388fd40cbe91ee027e (diff)
downloadFreeBSD-src-dde32853641c8191e1074cc8a3d9b3ae9facfa27.zip
FreeBSD-src-dde32853641c8191e1074cc8a3d9b3ae9facfa27.tar.gz
Major update of NCP requester:
Use mchain API to work with mbuf chains. Do not depend on INET and IPX options. Allocate ncp_rq structure dynamically to prevent possible stack overflows. Let ncp_request() dispose control structure if request failed. Move all NCP wrappers to ncp_ncp.c file and all NCP request processing functions to ncp_rq.c file. Improve reconnection logic. Misc style fixes.
Diffstat (limited to 'sys')
-rw-r--r--sys/netncp/ncp_conn.c161
-rw-r--r--sys/netncp/ncp_conn.h36
-rw-r--r--sys/netncp/ncp_login.c68
-rw-r--r--sys/netncp/ncp_mod.c121
-rw-r--r--sys/netncp/ncp_ncp.c623
-rw-r--r--sys/netncp/ncp_ncp.h18
-rw-r--r--sys/netncp/ncp_nls.c3
-rw-r--r--sys/netncp/ncp_nls.h2
-rw-r--r--sys/netncp/ncp_rq.c786
-rw-r--r--sys/netncp/ncp_rq.h99
-rw-r--r--sys/netncp/ncp_sock.c58
-rw-r--r--sys/netncp/ncp_sock.h3
-rw-r--r--sys/netncp/ncp_subr.c175
-rw-r--r--sys/netncp/ncp_subr.h17
14 files changed, 916 insertions, 1254 deletions
diff --git a/sys/netncp/ncp_conn.c b/sys/netncp/ncp_conn.c
index f020731..51151d2 100644
--- a/sys/netncp/ncp_conn.c
+++ b/sys/netncp/ncp_conn.c
@@ -41,8 +41,11 @@
#include <sys/sysctl.h>
#include <netncp/ncp.h>
+#include <netncp/nwerror.h>
#include <netncp/ncp_subr.h>
#include <netncp/ncp_conn.h>
+#include <netncp/ncp_sock.h>
+#include <netncp/ncp_ncp.h>
SLIST_HEAD(ncp_handle_head,ncp_handle);
@@ -72,31 +75,40 @@ SYSCTL_PROC(_net_ncp, OID_AUTO, conn_stat, CTLFLAG_RD|CTLTYPE_OPAQUE,
MALLOC_DEFINE(M_NCPDATA, "NCP data", "NCP private data");
int
-ncp_conn_init(void) {
+ncp_conn_init(void)
+{
lockinit(&listlock, PSOCK, "ncpll", 0, 0);
lockinit(&lhlock, PSOCK, "ncplh", 0, 0);
return 0;
}
int
-ncp_conn_destroy(void) {
+ncp_conn_destroy(void)
+{
+ if (ncp_conn_cnt) {
+ NCPERROR("There are %d connections active\n", ncp_conn_cnt);
+ return EBUSY;
+ }
lockdestroy(&listlock);
lockdestroy(&lhlock);
return 0;
}
int
-ncp_conn_locklist(int flags, struct proc *p){
+ncp_conn_locklist(int flags, struct proc *p)
+{
return lockmgr(&listlock, flags | LK_CANRECURSE, 0, p);
}
void
-ncp_conn_unlocklist(struct proc *p){
+ncp_conn_unlocklist(struct proc *p)
+{
lockmgr(&listlock, LK_RELEASE, 0, p);
}
int
-ncp_conn_access(struct ncp_conn *conn, struct ucred *cred, mode_t mode) {
+ncp_conn_access(struct ncp_conn *conn, struct ucred *cred, mode_t mode)
+{
int error;
if (cred == NOCRED || ncp_suser(cred) == 0 ||
@@ -110,7 +122,8 @@ ncp_conn_access(struct ncp_conn *conn, struct ucred *cred, mode_t mode) {
}
int
-ncp_conn_lock_any(struct ncp_conn *conn, struct proc *p, struct ucred *cred) {
+ncp_conn_lock_any(struct ncp_conn *conn, struct proc *p, struct ucred *cred)
+{
int error;
if (conn->nc_id == 0) return EACCES;
@@ -133,7 +146,8 @@ ncp_conn_lock_any(struct ncp_conn *conn, struct proc *p, struct ucred *cred) {
}
int
-ncp_conn_lock(struct ncp_conn *conn, struct proc *p, struct ucred *cred, int mode) {
+ncp_conn_lock(struct ncp_conn *conn, struct proc *p, struct ucred *cred, int mode)
+{
int error;
error = ncp_conn_access(conn,cred,mode);
@@ -145,7 +159,8 @@ ncp_conn_lock(struct ncp_conn *conn, struct proc *p, struct ucred *cred, int mod
* Lock conn but unlock connlist
*/
static int
-ncp_conn_lock2(struct ncp_conn *conn, struct proc *p, struct ucred *cred, int mode) {
+ncp_conn_lock2(struct ncp_conn *conn, struct proc *p, struct ucred *cred, int mode)
+{
int error;
error = ncp_conn_access(conn,cred,mode);
@@ -164,7 +179,8 @@ ncp_conn_lock2(struct ncp_conn *conn, struct proc *p, struct ucred *cred, int mo
}
void
-ncp_conn_unlock(struct ncp_conn *conn, struct proc *p) {
+ncp_conn_unlock(struct ncp_conn *conn, struct proc *p)
+{
/*
* note, that LK_RELASE will do wakeup() instead of wakeup_one().
* this will do a little overhead
@@ -183,11 +199,31 @@ ncp_conn_assert_locked(struct ncp_conn *conn,char *checker, struct proc *p){
* create, fill with defaults and return in locked state
*/
int
-ncp_conn_alloc(struct proc *p, struct ucred *cred, struct ncp_conn **conn)
+ncp_conn_alloc(struct ncp_conn_args *cap, struct proc *p, struct ucred *cred,
+ struct ncp_conn **conn)
{
- int error;
struct ncp_conn *ncp;
+ struct ucred *owner;
+ int error, isroot;
+ if (cap->saddr.sa_family != AF_INET && cap->saddr.sa_family != AF_IPX)
+ return EPROTONOSUPPORT;
+ isroot = ncp_suser(cred) == 0;
+ /*
+ * Only root can change ownership
+ */
+ if (cap->owner != NCP_DEFAULT_OWNER && !isroot)
+ return EPERM;
+ if (cap->group != NCP_DEFAULT_GROUP &&
+ !groupmember(cap->group, cred) && !isroot)
+ return EPERM;
+ if (cap->owner != NCP_DEFAULT_OWNER) {
+ owner = crget();
+ owner->cr_uid = cap->owner;
+ } else {
+ owner = cred;
+ crhold(owner);
+ }
MALLOC(ncp, struct ncp_conn *, sizeof(struct ncp_conn),
M_NCPDATA, M_WAITOK | M_ZERO);
error = 0;
@@ -197,6 +233,14 @@ ncp_conn_alloc(struct proc *p, struct ucred *cred, struct ncp_conn **conn)
ncp->nc_owner = cred;
ncp->seq = 0;
ncp->connid = 0xFFFF;
+ ncp->li = *cap;
+ ncp->nc_group = (cap->group != NCP_DEFAULT_GROUP) ?
+ cap->group : cred->cr_groups[0];
+
+ if (cap->retry_count == 0)
+ ncp->li.retry_count = NCP_RETRY_COUNT;
+ if (cap->timeout == 0)
+ ncp->li.timeout = NCP_RETRY_TIMEOUT;
ncp_conn_lock_any(ncp, p, ncp->nc_owner);
*conn = ncp;
ncp_conn_locklist(LK_EXCLUSIVE, p);
@@ -209,60 +253,93 @@ ncp_conn_alloc(struct proc *p, struct ucred *cred, struct ncp_conn **conn)
* Remove the connection, on entry it must be locked
*/
int
-ncp_conn_free(struct ncp_conn *ncp) {
+ncp_conn_free(struct ncp_conn *ncp)
+{
+ struct proc *p;
int error;
- struct ncp_conn *ncp1;
+ if (ncp == NULL) {
+ NCPFATAL("ncp == NULL\n");
+ return 0;
+ }
if (ncp->nc_id == 0) {
- printf("already!!!!\n");
+ NCPERROR("nc_id == 0\n");
return EACCES;
}
- if (ncp==NULL) {
- NCPFATAL("conn==NULL !\n");
- return(EIO);
- }
- error = ncp_conn_assert_locked(ncp, __FUNCTION__, ncp->procp);
- if (error) return error;
- if (ncp->ref_cnt) {
- NCPFATAL("there are %d referenses left\n",ncp->ref_cnt);
- return(EBUSY);
- }
+ p = ncp->procp;
+ error = ncp_conn_assert_locked(ncp, __FUNCTION__, p);
+ if (error)
+ return error;
+ if (ncp->ref_cnt != 0 || (ncp->flags & NCPFL_PERMANENT))
+ return EBUSY;
+ if (ncp_conn_access(ncp, ncp->ucred, NCPM_WRITE))
+ return EACCES;
+
+ if ((ncp->flags & (NCPFL_INVALID | NCPFL_ATTACHED)) == NCPFL_ATTACHED)
+ ncp_ncp_disconnect(ncp);
+ ncp_sock_disconnect(ncp);
+
/*
- * Mark conn as died and wait for other process
+ * Mark conn as dead and wait for other process
*/
ncp->nc_id = 0;
- ncp_conn_unlock(ncp,ncp->procp);
+ ncp_conn_unlock(ncp, p);
/*
* if signal is raised - how I do react ?
*/
- lockmgr(&ncp->nc_lock, LK_DRAIN, 0, ncp->procp);
+ lockmgr(&ncp->nc_lock, LK_DRAIN, 0, p);
lockdestroy(&ncp->nc_lock);
while (ncp->nc_lwant) {
printf("lwant = %d\n", ncp->nc_lwant);
tsleep(&ncp->nc_lwant, PZERO,"ncpdr",2*hz);
}
- ncp_conn_locklist(LK_EXCLUSIVE, ncp->procp);
- /*
- * It is possible, that other process destroy connection while we draining,
- * and free it. So, we must rescan list
- */
- SLIST_FOREACH(ncp1, &conn_list, nc_next) {
- if (ncp1 == ncp) break;
- }
- if (ncp1 == NULL) {
- ncp_conn_unlocklist(ncp->procp);
- return 0;
- }
+ ncp_conn_locklist(LK_EXCLUSIVE, p);
SLIST_REMOVE(&conn_list, ncp, ncp_conn, nc_next);
ncp_conn_cnt--;
- ncp_conn_unlocklist(ncp->procp);
- if (ncp->li.user) free(ncp->li.user, M_NCPDATA);
- if (ncp->li.password) free(ncp->li.password, M_NCPDATA);
+ ncp_conn_unlocklist(p);
+ if (ncp->li.user)
+ free(ncp->li.user, M_NCPDATA);
+ if (ncp->li.password)
+ free(ncp->li.password, M_NCPDATA);
crfree(ncp->nc_owner);
FREE(ncp, M_NCPDATA);
return (0);
}
+int
+ncp_conn_reconnect(struct ncp_conn *ncp)
+{
+ int error;
+
+ /*
+ * Close opened sockets if any
+ */
+ ncp_sock_disconnect(ncp);
+ error = ncp_sock_connect(ncp);
+ if (error)
+ return error;
+ error = ncp_ncp_connect(ncp);
+ if (error)
+ return error;
+ error = ncp_renegotiate_connparam(ncp, NCP_DEFAULT_BUFSIZE, 0);
+ if (error == NWE_SIGNATURE_LEVEL_CONFLICT) {
+ printf("Unable to negotiate requested security level\n");
+ error = EOPNOTSUPP;
+ }
+ if (error) {
+ ncp_ncp_disconnect(ncp);
+ return error;
+ }
+#ifdef NCPBURST
+ error = ncp_burst_connect(ncp);
+ if (error) {
+ ncp_ncp_disconnect(ncp);
+ return error;
+ }
+#endif
+ return 0;
+}
+
/*
* Lookup connection by handle, return a locked conn descriptor
*/
diff --git a/sys/netncp/ncp_conn.h b/sys/netncp/ncp_conn.h
index 0171421..df64eff 100644
--- a/sys/netncp/ncp_conn.h
+++ b/sys/netncp/ncp_conn.h
@@ -34,17 +34,13 @@
#ifndef _NETNCP_NCP_CONN_H_
#define _NETNCP_NCP_CONN_H_
-#ifdef INET
#ifndef _NETINET_IN_H_
#include <netinet/in.h>
#endif
-#endif
-#ifdef IPX
#ifndef _NETIPX_IPX_H_
#include <netipx/ipx.h>
#endif
-#endif
#ifndef _SYS_SOCKET_H_
#include <sys/socket.h>
@@ -55,14 +51,16 @@
#define NCP_ON_TCP 1*/
/* flags field in conn structure */
-#define NCPFL_SOCONN 0x01 /* socket layer is up */
-#define NCPFL_ATTACHED 0x02 /* ncp layer is up */
-#define NCPFL_LOGGED 0x04 /* logged in to server */
-#define NCPFL_INVALID 0x08 /* last request was not completed */
-#define NCPFL_INTR 0x10 /* interrupted call */
-#define NCPFL_RESTORING 0x20 /* trying to reconnect */
-#define NCPFL_PERMANENT 0x40 /* no way to kill conn, when this set */
-#define NCPFL_PRIMARY 0x80 /* have meaning only for owner */
+#define NCPFL_SOCONN 0x0001 /* socket layer is up */
+#define NCPFL_ATTACHED 0x0002 /* ncp layer is up */
+#define NCPFL_LOGGED 0x0004 /* logged in to server */
+#define NCPFL_INVALID 0x0008 /* last request was not completed */
+#define NCPFL_INTR 0x0010 /* interrupted call */
+#define NCPFL_RESTORING 0x0020 /* trying to reconnect */
+#define NCPFL_PERMANENT 0x0040 /* no way to kill conn, when this set */
+#define NCPFL_PRIMARY 0x0080 /* have meaning only for owner */
+#define NCPFL_WASATTACHED 0x0100 /* there was at least one successfull connect */
+#define NCPFL_WASLOGGED 0x0200 /* there was at least one successfull login */
#define NCPFL_SIGNACTIVE 0x1000 /* packet signing active */
#define NCPFL_SIGNWANTED 0x2000 /* signing should start */
@@ -92,12 +90,8 @@ struct ncp_conn_args {
u_int32_t objtype;
union {
struct sockaddr addr;
-#ifdef IPX
struct sockaddr_ipx ipxaddr;
-#endif
-#ifdef INET
struct sockaddr_in inaddr;
-#endif
} addr;
int timeout; /* ncp rq timeout */
int retry_count; /* counts to give an error */
@@ -181,7 +175,6 @@ struct ncp_conn {
int nc_lwant; /* number of wanted locks */
struct proc *procp; /* pid currently operates */
struct ucred *ucred; /* usr currently operates */
- struct ncp_rq *nc_rq; /* current request */
/* Fields used to process ncp requests */
int connid; /* assigned by server */
u_int8_t seq;
@@ -199,13 +192,10 @@ struct ncp_conn {
#endif
};
-#define ncp_conn_signwanted(conn) ((conn)->flags & NCPFL_SIGNWANTED)
-#define ncp_conn_valid(conn) ((conn->flags & NCPFL_INVALID) == 0)
-#define ncp_conn_invalidate(conn) {conn->flags |= NCPFL_INVALID;}
-
int ncp_conn_init(void);
int ncp_conn_destroy(void);
-int ncp_conn_alloc(struct proc *p,struct ucred *cred, struct ncp_conn **connid);
+int ncp_conn_alloc(struct ncp_conn_args *cap,
+ struct proc *p, struct ucred *cred, struct ncp_conn **connid);
int ncp_conn_free(struct ncp_conn *conn);
int ncp_conn_access(struct ncp_conn *conn,struct ucred *cred,mode_t mode);
int ncp_conn_lock(struct ncp_conn *conn,struct proc *p,struct ucred *cred,int mode);
@@ -228,6 +218,8 @@ int ncp_conn_getattached(struct ncp_conn_args *li,struct proc *p,struct ucred *
int ncp_conn_putprochandles(struct proc *p);
int ncp_conn_getinfo(struct ncp_conn *ncp, struct ncp_conn_stat *ncs);
+int ncp_conn_reconnect(struct ncp_conn *ncp);
+
extern struct ncp_conn_head conn_list;
extern int ncp_burst_enabled;
diff --git a/sys/netncp/ncp_login.c b/sys/netncp/ncp_login.c
index 7c3c1f2..b7e76c7 100644
--- a/sys/netncp/ncp_login.c
+++ b/sys/netncp/ncp_login.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, Boris Popov
+ * Copyright (c) 1999, 2000, 2001 Boris Popov
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -84,18 +84,20 @@ ncp_sign_start(struct ncp_conn *conn, char *logindata) {
* target is a 8-byte buffer
*/
int
-ncp_get_encryption_key(struct ncp_conn *conn, char *target) {
+ncp_get_encryption_key(struct ncp_conn *conn, char *target)
+{
+ struct ncp_rq *rqp;
int error;
- DECLARE_RQ;
- NCP_RQ_HEAD_S(23,23,conn->procp,conn->ucred);
- checkbad(ncp_request(conn,rqp));
- if (rqp->rpsize < 8) {
- NCPFATAL("rpsize=%d < 8\n", rqp->rpsize);
- return EIO;
- }
- ncp_rp_mem(rqp, target, 8);
- NCP_RQ_EXIT;
+ error = ncp_rq_alloc_subfn(23, 23, conn, conn->procp, conn->ucred, &rqp);
+ if (error)
+ return error;
+ rqp->nr_minrplen = 8;
+ error = ncp_request(rqp);
+ if (error)
+ return error;
+ md_get_mem(&rqp->rp, target, 8, MB_MSYSTEM);
+ ncp_rq_done(rqp);
return error;
}
@@ -122,27 +124,32 @@ ncp_login_object(struct ncp_conn *conn, unsigned char *username,
int
ncp_login_encrypted(struct ncp_conn *conn, struct ncp_bindery_object *object,
unsigned char *key, unsigned char *passwd,
- struct proc *p,struct ucred *cred) {
+ struct proc *p,struct ucred *cred)
+{
+ struct ncp_rq *rqp;
+ struct mbchain *mbp;
u_int32_t tmpID = htonl(object->object_id);
u_char buf[16 + 8];
u_char encrypted[8];
int error;
- DECLARE_RQ;
nw_keyhash((u_char*)&tmpID, passwd, strlen(passwd), buf);
nw_encrypt(key, buf, encrypted);
- NCP_RQ_HEAD_S(23,24,p,cred);
- ncp_rq_mem(rqp, encrypted, 8);
- ncp_rq_word_hl(rqp, object->object_type);
+ error = ncp_rq_alloc_subfn(23, 24, conn, p, cred, &rqp);
+ if (error)
+ return error;
+ mbp = &rqp->rq;
+ mb_put_mem(mbp, encrypted, 8, MB_MSYSTEM);
+ mb_put_uint16be(mbp, object->object_type);
ncp_rq_pstring(rqp, object->object_name);
- error = ncp_request(conn, rqp);
- NCP_RQ_EXIT_NB;
- if (conn->flags & NCPFL_SIGNWANTED) {
- if (error == 0 || error == NWE_PASSWORD_EXPIRED) {
- memcpy(buf + 16, key, 8);
- error = ncp_sign_start(conn, buf);
- }
+ error = ncp_request(rqp);
+ if (!error)
+ ncp_rq_done(rqp);
+ if ((conn->flags & NCPFL_SIGNWANTED) &&
+ (error == 0 || error == NWE_PASSWORD_EXPIRED)) {
+ bcopy(key, buf + 16, 8);
+ error = ncp_sign_start(conn, buf);
}
return error;
}
@@ -152,15 +159,18 @@ ncp_login_unencrypted(struct ncp_conn *conn, u_int16_t object_type,
char *object_name, unsigned char *passwd,
struct proc *p, struct ucred *cred)
{
+ struct ncp_rq *rqp;
int error;
- DECLARE_RQ;
- NCP_RQ_HEAD_S(23,20,conn->procp,conn->ucred);
- ncp_rq_word_hl(rqp, object_type);
+ error = ncp_rq_alloc_subfn(23, 20, conn, p, cred, &rqp);
+ if (error)
+ return error;
+ mb_put_uint16be(&rqp->rq, object_type);
ncp_rq_pstring(rqp, object_name);
ncp_rq_pstring(rqp, passwd);
- error = ncp_request(conn,rqp);
- NCP_RQ_EXIT_NB;
+ error = ncp_request(rqp);
+ if (!error)
+ ncp_rq_done(rqp);
return error;
}
@@ -188,7 +198,7 @@ ncp_login(struct ncp_conn *conn, char *user, int objtype, char *password,
ncp_str_upper(conn->li.password);
checkbad(ncp_login_object(conn, conn->li.user, objtype, conn->li.password,p,cred));
conn->li.objtype = objtype;
- conn->flags |= NCPFL_LOGGED;
+ conn->flags |= NCPFL_LOGGED | NCPFL_WASLOGGED;
return 0;
bad:
if (conn->li.user) free(conn->li.user, M_NCPDATA);
diff --git a/sys/netncp/ncp_mod.c b/sys/netncp/ncp_mod.c
index 11df855..ee8d995 100644
--- a/sys/netncp/ncp_mod.c
+++ b/sys/netncp/ncp_mod.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, Boris Popov
+ * Copyright (c) 1999, 2000, 2001 Boris Popov
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -58,6 +58,7 @@ SYSCTL_INT(_net_ncp, OID_AUTO, sysent, CTLFLAG_RD, &ncp_sysent, 0, "");
SYSCTL_INT(_net_ncp, OID_AUTO, version, CTLFLAG_RD, &ncp_version, 0, "");
MODULE_VERSION(ncp, 1);
+MODULE_DEPEND(ncp, libmchain, 1, 1, 1);
static int
ncp_conn_frag_rq(struct ncp_conn *conn, struct proc *p, struct ncp_conn_frag *nfp);
@@ -71,7 +72,8 @@ struct sncp_connect_args {
};
static int
-__P(sncp_connect(struct proc *p, struct sncp_connect_args *uap)){
+sncp_connect(struct proc *p, struct sncp_connect_args *uap)
+{
int connHandle = 0, error;
struct ncp_conn *conn;
struct ncp_handle *handle;
@@ -82,7 +84,12 @@ __P(sncp_connect(struct proc *p, struct sncp_connect_args *uap)){
li.password = li.user = NULL;
error = ncp_conn_getattached(&li, p, p->p_ucred, NCPM_WRITE | NCPM_EXECUTE, &conn);
if (error) {
- error = ncp_connect(&li, p, p->p_ucred, &conn);
+ error = ncp_conn_alloc(&li, p, p->p_ucred, &conn);
+ if (error)
+ goto bad;
+ error = ncp_conn_reconnect(conn);
+ if (error)
+ ncp_conn_free(conn);
}
if (!error) {
error = ncp_conn_gethandle(conn, p, &handle);
@@ -104,35 +111,41 @@ static int ncp_conn_handler(struct proc *p, struct sncp_request_args *uap,
struct ncp_conn *conn, struct ncp_handle *handle);
static int
-__P(sncp_request(struct proc *p, struct sncp_request_args *uap)){
- int error = 0, rqsize;
+sncp_request(struct proc *p, struct sncp_request_args *uap)
+{
+ struct ncp_rq *rqp;
struct ncp_conn *conn;
struct ncp_handle *handle;
- DECLARE_RQ;
+ int error = 0, rqsize;
error = ncp_conn_findhandle(uap->connHandle,p,&handle);
- if (error) return error;
+ if (error)
+ return error;
conn = handle->nh_conn;
if (uap->fn == NCP_CONN)
return ncp_conn_handler(p, uap, conn, handle);
error = copyin(&uap->ncpbuf->rqsize, &rqsize, sizeof(int));
- if (error) return(error);
- error = ncp_conn_lock(conn,p,p->p_ucred,NCPM_EXECUTE);
- if (error) return(error);
- ncp_rq_head(rqp,NCP_REQUEST,uap->fn,p,p->p_ucred);
- if (rqsize)
- error = ncp_rq_usermem(rqp,(caddr_t)uap->ncpbuf->packet, rqsize);
- if (!error) {
- error = ncp_request(conn, rqp);
- if (error == 0 && rqp->rpsize)
- ncp_rp_usermem(rqp, (caddr_t)uap->ncpbuf->packet,
- rqp->rpsize);
- copyout(&rqp->cs, &uap->ncpbuf->cs, sizeof(rqp->cs));
- copyout(&rqp->cc, &uap->ncpbuf->cc, sizeof(rqp->cc));
- copyout(&rqp->rpsize, &uap->ncpbuf->rpsize, sizeof(rqp->rpsize));
+ if (error)
+ return(error);
+ error = ncp_rq_alloc(uap->fn, conn, p, p->p_ucred, &rqp);
+ if (error)
+ return error;
+ if (rqsize) {
+ error = mb_put_mem(&rqp->rq, (caddr_t)uap->ncpbuf->packet,
+ rqsize, MB_MUSER);
+ if (error)
+ goto bad;
}
+ rqp->nr_flags |= NCPR_DONTFREEONERR;
+ error = ncp_request(rqp);
+ if (error == 0 && rqp->nr_rpsize)
+ error = md_get_mem(&rqp->rp, (caddr_t)uap->ncpbuf->packet,
+ rqp->nr_rpsize, MB_MUSER);
+ copyout(&rqp->nr_cs, &uap->ncpbuf->cs, sizeof(rqp->nr_cs));
+ copyout(&rqp->nr_cc, &uap->ncpbuf->cc, sizeof(rqp->nr_cc));
+ copyout(&rqp->nr_rpsize, &uap->ncpbuf->rpsize, sizeof(rqp->nr_rpsize));
+bad:
ncp_rq_done(rqp);
- ncp_conn_unlock(conn,p);
return error;
}
@@ -170,14 +183,11 @@ ncp_conn_handler(struct proc *p, struct sncp_request_args *uap,
auio.uio_segflg = UIO_USERSPACE;
auio.uio_rw = (subfn == NCP_CONN_READ) ? UIO_READ : UIO_WRITE;
auio.uio_procp = p;
- error = ncp_conn_lock(conn,p,cred,NCPM_EXECUTE);
- if (error) return(error);
if (subfn == NCP_CONN_READ)
error = ncp_read(conn, &rwrq.nrw_fh, &auio, cred);
else
error = ncp_write(conn, &rwrq.nrw_fh, &auio, cred);
rwrq.nrw_cnt -= auio.uio_resid;
- ncp_conn_unlock(conn,p);
p->p_retval[0] = rwrq.nrw_cnt;
break;
} /* case int_read/write */
@@ -284,7 +294,7 @@ ncp_conn_handler(struct proc *p, struct sncp_request_args *uap,
error = ncp_conn_lock(conn, p, cred, NCPM_EXECUTE);
if (error) break;
ncp_conn_puthandle(hp, p, 0);
- error = ncp_disconnect(conn);
+ error = ncp_conn_free(conn);
if (error)
ncp_conn_unlock(conn, p);
break;
@@ -301,7 +311,8 @@ struct sncp_conn_scan_args {
};
static int
-__P(sncp_conn_scan(struct proc *p, struct sncp_conn_scan_args *uap)){
+sncp_conn_scan(struct proc *p, struct sncp_conn_scan_args *uap)
+{
int connHandle = 0, error;
struct ncp_conn_args li, *lip;
struct ncp_conn *conn;
@@ -350,32 +361,45 @@ __P(sncp_conn_scan(struct proc *p, struct sncp_conn_scan_args *uap)){
}
int
-ncp_conn_frag_rq(struct ncp_conn *conn, struct proc *p, struct ncp_conn_frag *nfp){
- int error = 0, i, rpsize;
- u_int32_t fsize;
+ncp_conn_frag_rq(struct ncp_conn *conn, struct proc *p, struct ncp_conn_frag *nfp)
+{
NW_FRAGMENT *fp;
- DECLARE_RQ;
+ struct ncp_rq *rqp;
+ u_int32_t fsize;
+ int error, i, rpsize;
- ncp_rq_head(rqp,NCP_REQUEST,nfp->fn,p,p->p_ucred);
- if (nfp->rqfcnt) {
- for(fp = nfp->rqf, i = 0; i < nfp->rqfcnt; i++, fp++) {
- checkbad(ncp_rq_usermem(rqp,(caddr_t)fp->fragAddress, fp->fragSize));
- }
+ error = ncp_rq_alloc(nfp->fn, conn, p, p->p_ucred, &rqp);
+ if (error)
+ return error;
+ for(fp = nfp->rqf, i = 0; i < nfp->rqfcnt; i++, fp++) {
+ error = mb_put_mem(&rqp->rq, (caddr_t)fp->fragAddress, fp->fragSize, MB_MUSER);
+ if (error)
+ goto bad;
}
- checkbad(ncp_request(conn, rqp));
- rpsize = rqp->rpsize;
+ rqp->nr_flags |= NCPR_DONTFREEONERR;
+ error = ncp_request(rqp);
+ if (error)
+ goto bad;
+ rpsize = rqp->nr_rpsize;
if (rpsize && nfp->rpfcnt) {
for(fp = nfp->rpf, i = 0; i < nfp->rpfcnt; i++, fp++) {
- checkbad(copyin(&fp->fragSize, &fsize, sizeof (fsize)));
+ error = copyin(&fp->fragSize, &fsize, sizeof (fsize));
+ if (error)
+ break;
fsize = min(fsize, rpsize);
- checkbad(ncp_rp_usermem(rqp,(caddr_t)fp->fragAddress, fsize));
+ error = md_get_mem(&rqp->rp, (caddr_t)fp->fragAddress, fsize, MB_MUSER);
+ if (error)
+ break;
rpsize -= fsize;
- checkbad(copyout(&fsize, &fp->fragSize, sizeof (fsize)));
+ error = copyout(&fsize, &fp->fragSize, sizeof (fsize));
+ if (error)
+ break;
}
}
- nfp->cs = rqp->cs;
- nfp->cc = rqp->cc;
- NCP_RQ_EXIT;
+ nfp->cs = rqp->nr_cs;
+ nfp->cc = rqp->nr_cc;
+bad:
+ ncp_rq_done(rqp);
return error;
}
@@ -454,8 +478,13 @@ ncp_load(void) {
}
static int
-ncp_unload(void) {
- ncp_done();
+ncp_unload(void)
+{
+ int error;
+
+ error = ncp_done();
+ if (error)
+ return error;
bcopy(&oldent, &sysent[ncp_sysent], sizeof(struct sysent) * SC_SIZE);
printf( "ncp_unload: unloaded\n");
return 0;
diff --git a/sys/netncp/ncp_ncp.c b/sys/netncp/ncp_ncp.c
index 69a7776..43a388b 100644
--- a/sys/netncp/ncp_ncp.c
+++ b/sys/netncp/ncp_ncp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, Boris Popov
+ * Copyright (c) 1999, 2000, 2001 Boris Popov
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,21 +33,17 @@
*
* Core of NCP protocol
*/
-#include "opt_inet.h"
-#include "opt_ipx.h"
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/systm.h>
#include <sys/proc.h>
-#include <sys/poll.h>
#include <sys/signalvar.h>
#include <sys/mbuf.h>
+#include <sys/uio.h>
-#ifdef IPX
#include <netipx/ipx.h>
#include <netipx/ipx_var.h>
-#endif
#include <netncp/ncp.h>
#include <netncp/ncp_conn.h>
@@ -57,12 +53,6 @@
#include <netncp/ncp_rq.h>
#include <netncp/nwerror.h>
-static int ncp_do_request(struct ncp_conn *,struct ncp_rq *rqp);
-static int ncp_negotiate_buffersize(struct ncp_conn *conn, int size, int *target);
-static int ncp_renegotiate_connparam(struct ncp_conn *conn, int buffsize, int in_options);
-static void ncp_sign_packet(struct ncp_conn *conn, struct ncp_rq *rqp, int *size);
-
-
#ifdef NCP_DATA_DEBUG
static
void m_dumpm(struct mbuf *m) {
@@ -103,374 +93,132 @@ ncp_chkintr(struct ncp_conn *conn, struct proc *p)
* should be called with LOCKED connection, also they use procp & ucred
*/
int
-ncp_ncp_connect(struct ncp_conn *conn) {
- int error;
+ncp_ncp_connect(struct ncp_conn *conn)
+{
+ struct ncp_rq *rqp;
struct ncp_rphdr *rp;
- DECLARE_RQ;
+ int error;
- conn->flags &= ~(NCPFL_INVALID | NCPFL_SIGNACTIVE | NCPFL_SIGNWANTED);
+ error = ncp_rq_alloc_any(NCP_ALLOC_SLOT, 0, conn, conn->procp, conn->ucred, &rqp);
+ if (error)
+ return error;
+
+ conn->flags &= ~(NCPFL_INVALID | NCPFL_SIGNACTIVE | NCPFL_SIGNWANTED
+ | NCPFL_ATTACHED);
conn->seq = 0;
- checkbad(ncp_rq_head(rqp,NCP_ALLOC_SLOT,0,conn->procp,conn->ucred));
- error=ncp_do_request(conn,rqp);
+ error = ncp_request_int(rqp);
if (!error) {
- rp = mtod(rqp->rp, struct ncp_rphdr*);
+ rp = mtod(rqp->rp.md_top, struct ncp_rphdr*);
conn->connid = rp->conn_low + (rp->conn_high << 8);
}
ncp_rq_done(rqp);
- if (error) return error;
- conn->flags |= NCPFL_ATTACHED;
-
- error = ncp_renegotiate_connparam(conn, NCP_DEFAULT_BUFSIZE, 0);
- if (error == NWE_SIGNATURE_LEVEL_CONFLICT) {
- printf("Unable to negotiate requested security level\n");
- error = EOPNOTSUPP;
- }
- if (error) {
- ncp_ncp_disconnect(conn);
+ if (error)
return error;
- }
-#ifdef NCPBURST
- ncp_burst_connect(conn);
-#endif
-bad:
- return error;
+ conn->flags |= NCPFL_ATTACHED | NCPFL_WASATTACHED;
+ return 0;
}
int
-ncp_ncp_disconnect(struct ncp_conn *conn) {
+ncp_ncp_disconnect(struct ncp_conn *conn)
+{
+ struct ncp_rq *rqp;
int error;
- struct ncp_rqhdr *ncprq;
- DECLARE_RQ;
NCPSDEBUG("for connid=%d\n",conn->nc_id);
#ifdef NCPBURST
ncp_burst_disconnect(conn);
#endif
- error=ncp_rq_head(rqp,NCP_FREE_SLOT,0,conn->procp,conn->ucred);
- ncprq = mtod(rqp->rq,struct ncp_rqhdr*);
- error=ncp_do_request(conn,rqp);
- ncp_rq_done(rqp);
- ncp_conn_invalidate(conn);
- ncp_sock_disconnect(conn);
- return 0;
-}
-/*
- * Make a signature for the current packet and add it at the end of the
- * packet.
- */
-static void
-ncp_sign_packet(struct ncp_conn *conn, struct ncp_rq *rqp, int *size) {
- u_char data[64];
-
- bzero(data, sizeof(data));
- bcopy(conn->sign_root, data, 8);
- setdle(data, 8, *size);
- m_copydata(rqp->rq, sizeof(struct ncp_rqhdr)-1,
- min((*size) - sizeof(struct ncp_rqhdr)+1, 52),data+12);
- ncp_sign(conn->sign_state, data, conn->sign_state);
- ncp_rq_mem(rqp, (void*)conn->sign_state, 8);
- (*size) += 8;
-}
-
-/*
- * Low level send rpc, here we do not attempt to restore any connection,
- * Connection expected to be locked
- */
-static int
-ncp_do_request(struct ncp_conn *conn, struct ncp_rq *rqp) {
- int error=EIO,len, dosend, plen = 0, gotpacket, s;
- struct socket *so;
- struct proc *p = conn->procp;
- struct ncp_rqhdr *rq;
- struct ncp_rphdr *rp=NULL;
- struct timeval tv;
- struct mbuf *m, *mreply = NULL;
-
- conn->nc_rq = rqp;
- rqp->conn = conn;
- if (p == NULL)
- p = curproc; /* XXX maybe procpage ? */
- if (!ncp_conn_valid(conn)) {
- printf("%s: conn not valid\n",__FUNCTION__);
- return (error);
- }
- so = conn->ncp_so;
- if (!so) {
- printf("%s: ncp_so is NULL !\n",__FUNCTION__);
- ncp_conn_invalidate(conn); /* wow ! how we do that ? */
- return EBADF;
- }
- /*
- * Flush out replies on previous reqs
- */
- s = splnet();
- while (1/*so->so_rcv.sb_cc*/) {
- if (ncp_poll(so,POLLIN) == 0) break;
- if (ncp_sock_recv(so,&m,&len) != 0) break;
- m_freem(m);
- }
- rq = mtod(rqp->rq,struct ncp_rqhdr *);
- rq->seq = conn->seq;
- m = rqp->rq;
- len = 0;
- while (m) {
- len += m->m_len;
- m = m->m_next;
- }
- rqp->rq->m_pkthdr.len = len;
- switch(rq->fn) {
- case 0x15: case 0x16: case 0x17: case 0x23:
- m = rqp->rq;
- *((u_int16_t*)(mtod(m,u_int8_t*)+sizeof(*rq))) = htons(len-2-sizeof(*rq));
- break;
- }
- if (conn->flags & NCPFL_SIGNACTIVE) {
- ncp_sign_packet(conn, rqp, &len);
- rqp->rq->m_pkthdr.len = len;
- }
- rq->conn_low = conn->connid & 0xff;
- /* rq->task = p->p_pgrp->pg_id & 0xff; */ /*p->p_pid*/
- /* XXX: this is temporary fix till I find a better solution */
- rq->task = rq->conn_low;
- rq->conn_high = conn->connid >> 8;
- rqp->rexmit = conn->li.retry_count;
- for(dosend = 1;;) {
- if (rqp->rexmit-- == 0) {
- error = ETIMEDOUT;
- break;
+ if (conn->flags & NCPFL_ATTACHED) {
+ error = ncp_rq_alloc_any(NCP_FREE_SLOT, 0, conn, conn->procp, conn->ucred, &rqp);
+ if (!error) {
+ ncp_request_int(rqp);
+ ncp_rq_done(rqp);
}
- error = 0;
- if (dosend) {
- NCPSDEBUG("send:%04x f=%02x c=%d l=%d s=%d t=%d\n",rq->type, rq->fn, (rq->conn_high << 8) + rq->conn_low,
- rqp->rq->m_pkthdr.len, rq->seq, rq->task
- );
- error = ncp_sock_send(so, rqp->rq, rqp);
- if (error) break;
- }
- tv.tv_sec = conn->li.timeout;
- tv.tv_usec = 0;
- error = ncp_sock_rselect(so, p, &tv, POLLIN);
- if (error == EWOULDBLOCK ) /* timeout expired */
- continue;
- error = ncp_chkintr(conn, p);
- if (error == EINTR) /* we dont restart */
- break;
- if (error) break;
- /*
- * At this point it is possible to get more than one
- * reply from server. In general, last reply should be for
- * current request, but not always. So, we loop through
- * all replies to find the right answer and flush others.
- */
- gotpacket = 0; /* nothing good found */
- dosend = 1; /* resend rq if error */
- for (;;) {
- error = 0;
- if (ncp_poll(so,POLLIN) == 0) break;
-/* if (so->so_rcv.sb_cc == 0) {
- break;
- }*/
- error = ncp_sock_recv(so,&m,&len);
- if (error) break; /* must be more checks !!! */
- if (m->m_len < sizeof(*rp)) {
- m = m_pullup(m, sizeof(*rp));
- if (m == NULL) {
- printf("%s: reply too short\n",__FUNCTION__);
- continue;
- }
- }
- rp = mtod(m, struct ncp_rphdr*);
- if (len == sizeof(*rp) && rp->type == NCP_POSITIVE_ACK) {
- NCPSDEBUG("got positive acknowledge\n");
- m_freem(m);
- rqp->rexmit = conn->li.retry_count;
- dosend = 0; /* server just busy and will reply ASAP */
- continue;
- }
- NCPSDEBUG("recv:%04x c=%d l=%d s=%d t=%d cc=%02x cs=%02x\n",rp->type,
- (rp->conn_high << 8) + rp->conn_low, len, rp->seq, rp->task,
- rp->completion_code, rp->connection_state);
- NCPDDEBUG(m);
- if ( (rp->type == NCP_REPLY) &&
- ((rq->type == NCP_ALLOC_SLOT) ||
- ((rp->conn_low == rq->conn_low) &&
- (rp->conn_high == rq->conn_high)
- ))) {
- if (rq->seq > rp->seq || (rq->seq == 0 && rp->seq == 0xff)) {
- dosend = 1;
- }
- if (rp->seq == rq->seq) {
- if (gotpacket) {
- m_freem(m);
- } else {
- gotpacket = 1;
- mreply = m;
- plen = len;
- }
- continue; /* look up other for other packets */
- }
- }
- m_freem(m);
- NCPSDEBUG("reply mismatch\n");
- } /* for receive */
- if (error) break;
- if (gotpacket) break;
- /* try to resend, or just wait */
- }
- splx(s);
- conn->seq++;
- if (error) {
- NCPSDEBUG("error=%d\n",error);
- if (error != EINTR) /* if not just interrupt */
- ncp_conn_invalidate(conn); /* only reconnect to restore */
- return(error);
- }
- if (conn->flags & NCPFL_SIGNACTIVE) {
- /* XXX: check reply signature */
- m_adj(mreply, -8);
- plen -= 8;
}
- len = plen;
- m = mreply;
- rp = mtod(m, struct ncp_rphdr*);
- len -= sizeof(*rp);
- rqp->rpsize = len;
- rqp->cc = error = rp->completion_code;
- if (error) error |= 0x8900; /* server error */
- rqp->cs = rp->connection_state;
- if (rqp->cs & (NCP_CS_BAD_CONN | NCP_CS_SERVER_DOWN)) {
- NCPSDEBUG("server drop us\n");
- ncp_conn_invalidate(conn);
- error = ECONNRESET;
- }
- rqp->rp = m;
- rqp->mrp = m;
- rqp->bpos = mtod(m, caddr_t) + sizeof(*rp);
- return error;
+ conn->flags |= NCPFL_INVALID;
+ ncp_sock_disconnect(conn);
+ return 0;
}
/*
- * Here we will try to restore any loggedin & dropped connection,
- * connection should be locked on entry
+ * All negotiation functions expect a locked connection
*/
-int ncp_restore_login(struct ncp_conn *conn);
-int
-ncp_restore_login(struct ncp_conn *conn) {
- int error, oldflags;
-
- if (conn->flags & NCPFL_RESTORING) {
- printf("Hey, ncp_restore_login called twise !!!\n");
- return 0;
- }
- oldflags = conn->flags;
- printf("Restoring connection, flags = %d\n",oldflags);
- if ((oldflags & NCPFL_LOGGED) == 0) {
- return ECONNRESET; /* no need to restore empty conn */
- }
- conn->flags &= ~(NCPFL_LOGGED | NCPFL_ATTACHED);
- conn->flags |= NCPFL_RESTORING;
- do { /* not a loop */
- error = ncp_reconnect(conn);
- if (error) break;
- if (conn->li.user)
- error = ncp_login_object(conn, conn->li.user, conn->li.objtype, conn->li.password,conn->procp,conn->ucred);
- if (error) break;
- conn->flags |= NCPFL_LOGGED;
- } while(0);
- if (error) {
- conn->flags = oldflags | NCPFL_INVALID;
- }
- conn->flags &= ~NCPFL_RESTORING;
- return error;
-}
int
-ncp_request(struct ncp_conn *conn, struct ncp_rq *rqp) {
- int error, rcnt;
-/* struct ncp_rqhdr *rq = mtod(rqp->rq,struct ncp_rqhdr*);*/
-
- error = ncp_conn_lock(conn,rqp->p,rqp->cred,NCPM_EXECUTE);
- if (error) return error;
- rcnt = NCP_RESTORE_COUNT;
- for(;;) {
- if (!ncp_conn_valid(conn)) {
- if (rcnt==0) {
- error = ECONNRESET;
- break;
- }
- rcnt--;
- error = ncp_restore_login(conn);
- if (error)
- continue;
- }
- error=ncp_do_request(conn, rqp);
- if (ncp_conn_valid(conn)) /* not just error ! */
- break;
- }
- ncp_conn_unlock(conn,rqp->p);
- return error;
-}
-
-/*
- * All negotiation functions expect a locked connection
- */
-static int
-ncp_negotiate_buffersize(struct ncp_conn *conn, int size, int *target) {
+ncp_negotiate_buffersize(struct ncp_conn *conn, int size, int *target)
+{
+ struct ncp_rq *rqp;
+ u_int16_t bsize;
int error;
- DECLARE_RQ;
- NCP_RQ_HEAD(0x21,conn->procp,conn->ucred);
- ncp_rq_word_hl(rqp, size);
- checkbad(ncp_request(conn,rqp));
- *target = min(ncp_rp_word_hl(rqp), size);
- NCP_RQ_EXIT;
+ error = ncp_rq_alloc(0x21, conn, conn->procp, conn->ucred, &rqp);
+ if (error)
+ return error;
+ mb_put_uint16be(&rqp->rq, size);
+ error = ncp_request(rqp);
+ if (error)
+ return error;
+ md_get_uint16be(&rqp->rp, &bsize);
+ *target = min(bsize, size);
+ ncp_rq_done(rqp);
return error;
}
static int
ncp_negotiate_size_and_options(struct ncp_conn *conn, int size, int options,
- int *ret_size, int *ret_options) {
+ int *ret_size, u_int8_t *ret_options)
+{
+ struct ncp_rq *rqp;
+ u_int16_t rs;
int error;
- int rs;
- DECLARE_RQ;
- NCP_RQ_HEAD(0x61,conn->procp,conn->ucred);
- ncp_rq_word_hl(rqp, size);
- ncp_rq_byte(rqp, options);
- checkbad(ncp_request(conn, rqp));
- rs = ncp_rp_word_hl(rqp);
+ error = ncp_rq_alloc(0x61, conn, conn->procp, conn->ucred, &rqp);
+ if (error)
+ return error;
+ mb_put_uint16be(&rqp->rq, size);
+ mb_put_uint8(&rqp->rq, options);
+ rqp->nr_minrplen = 2 + 2 + 1;
+ error = ncp_request(rqp);
+ if (error)
+ return error;
+ md_get_uint16be(&rqp->rp, &rs);
*ret_size = (rs == 0) ? size : min(rs, size);
- ncp_rp_word_hl(rqp); /* skip echo socket */
- *ret_options = ncp_rp_byte(rqp);
- NCP_RQ_EXIT;
+ md_get_uint16be(&rqp->rp, &rs); /* skip echo socket */
+ md_get_uint8(&rqp->rp, ret_options);
+ ncp_rq_done(rqp);
return error;
}
-static int
-ncp_renegotiate_connparam(struct ncp_conn *conn, int buffsize, int in_options)
+int
+ncp_renegotiate_connparam(struct ncp_conn *conn, int buffsize, u_int8_t in_options)
{
- int neg_buffsize, error, options, sl;
+ u_int8_t options;
+ int neg_buffsize, error, sl, ckslevel, ilen;
sl = conn->li.sig_level;
if (sl >= 2)
in_options |= NCP_SECURITY_LEVEL_SIGN_HEADERS;
-#ifdef IPX
- if (ipxcksum == 2)
- in_options |= NCP_IPX_CHECKSUM;
-#endif
+ if (conn->li.saddr.sa_family == AF_IPX) {
+ ilen = sizeof(ckslevel);
+ error = ncp_sysctlbyname("net.ipx.ipx.checksum", &ckslevel, &ilen,
+ NULL, 0, NULL);
+ if (error)
+ return error;
+ if (ckslevel == 2)
+ in_options |= NCP_IPX_CHECKSUM;
+ }
error = ncp_negotiate_size_and_options(conn, buffsize, in_options,
&neg_buffsize, &options);
if (!error) {
-#ifdef IPX
- if ((options ^ in_options) & NCP_IPX_CHECKSUM) {
- if (ipxcksum == 2) {
+ if (conn->li.saddr.sa_family == AF_IPX &&
+ ((options ^ in_options) & NCP_IPX_CHECKSUM)) {
+ if (ckslevel == 2) {
printf("Server refuses to support IPX checksums\n");
return NWE_REQUESTER_FAILURE;
}
in_options |= NCP_IPX_CHECKSUM;
error = 1;
}
-#endif /* IPX */
if ((options ^ in_options) & 2) {
if (sl == 0 || sl == 3)
return NWE_SIGNATURE_LEVEL_CONFLICT;
@@ -497,115 +245,148 @@ ncp_renegotiate_connparam(struct ncp_conn *conn, int buffsize, int in_options)
conn->buffer_size = neg_buffsize;
if (in_options & NCP_SECURITY_LEVEL_SIGN_HEADERS)
conn->flags |= NCPFL_SIGNWANTED;
-#ifdef IPX
- ncp_sock_checksum(conn, in_options & NCP_IPX_CHECKSUM);
-#endif
+ if (conn->li.saddr.sa_family == AF_IPX)
+ ncp_sock_checksum(conn, in_options & NCP_IPX_CHECKSUM);
return 0;
}
-int
-ncp_reconnect(struct ncp_conn *conn) {
- int error;
-
- /* close any open sockets */
- ncp_sock_disconnect(conn);
- switch( conn->li.saddr.sa_family ) {
-#ifdef IPX
- case AF_IPX:
- error = ncp_sock_connect_ipx(conn);
- break;
-#endif
-#ifdef INET
- case AF_INET:
- error = ncp_sock_connect_in(conn);
- break;
-#endif
- default:
- return EPROTONOSUPPORT;
+void
+ncp_check_rq(struct ncp_conn *conn){
+ return;
+ if (conn->flags & NCPFL_INTR) return;
+ /* first, check for signals */
+ if (ncp_chkintr(conn,conn->procp)) {
+ conn->flags |= NCPFL_INTR;
}
- if (!error)
- error = ncp_ncp_connect(conn);
- return error;
+ return;
}
-/*
- * Create conn structure and try to do low level connect
- * Server addr should be filled in.
- */
int
-ncp_connect(struct ncp_conn_args *li, struct proc *p, struct ucred *cred,
- struct ncp_conn **aconn)
+ncp_get_bindery_object_id(struct ncp_conn *conn,
+ u_int16_t object_type, char *object_name,
+ struct ncp_bindery_object *target,
+ struct proc *p,struct ucred *cred)
{
- struct ncp_conn *conn;
- struct ucred *owner;
- int error, isroot;
+ struct ncp_rq *rqp;
+ int error;
- if (li->saddr.sa_family != AF_INET && li->saddr.sa_family != AF_IPX)
- return EPROTONOSUPPORT;
- isroot = ncp_suser(cred) == 0;
- /*
- * Only root can change ownership
- */
- if (li->owner != NCP_DEFAULT_OWNER && !isroot)
- return EPERM;
- if (li->group != NCP_DEFAULT_GROUP &&
- !groupmember(li->group, cred) && !isroot)
- return EPERM;
- if (li->owner != NCP_DEFAULT_OWNER) {
- owner = crget();
- owner->cr_uid = li->owner;
- } else {
- owner = cred;
- crhold(owner);
- }
- error = ncp_conn_alloc(p, owner, &conn);
+ error = ncp_rq_alloc_subfn(23, 53, conn, conn->procp, conn->ucred, &rqp);
+ mb_put_uint16be(&rqp->rq, object_type);
+ ncp_rq_pstring(rqp, object_name);
+ rqp->nr_minrplen = 54;
+ error = ncp_request(rqp);
if (error)
- return (error);
- if (error) {
- ncp_conn_free(conn);
return error;
- }
- conn->li = *li;
- conn->nc_group = (li->group != NCP_DEFAULT_GROUP) ?
- li->group : cred->cr_groups[0];
-
- if (li->retry_count == 0)
- conn->li.retry_count = NCP_RETRY_COUNT;
- if (li->timeout == 0)
- conn->li.timeout = NCP_RETRY_TIMEOUT;
- error = ncp_reconnect(conn);
- if (error) {
- ncp_disconnect(conn);
- } else {
- *aconn=conn;
- }
- return error;
+ md_get_uint32be(&rqp->rp, &target->object_id);
+ md_get_uint16be(&rqp->rp, &target->object_type);
+ md_get_mem(&rqp->rp, (caddr_t)target->object_name, 48, MB_MSYSTEM);
+ ncp_rq_done(rqp);
+ return 0;
}
-/*
- * Break connection and deallocate memory
- */
+
int
-ncp_disconnect(struct ncp_conn *conn) {
+ncp_read(struct ncp_conn *conn, ncp_fh *file, struct uio *uiop, struct ucred *cred)
+{
+ struct ncp_rq *rqp;
+ struct mbchain *mbp;
+ u_int16_t retlen = 0 ;
+ int error = 0, len = 0, tsiz, burstio;
+
+ tsiz = uiop->uio_resid;
+#ifdef NCPBURST
+ burstio = (ncp_burst_enabled && tsiz > conn->buffer_size);
+#else
+ burstio = 0;
+#endif
- if (ncp_conn_access(conn,conn->ucred,NCPM_WRITE))
- return EACCES;
- if (conn->ref_cnt != 0) return EBUSY;
- if (conn->flags & NCPFL_PERMANENT) return EBUSY;
- if (ncp_conn_valid(conn)) {
- ncp_ncp_disconnect(conn);
+ while (tsiz > 0) {
+ if (!burstio) {
+ len = min(4096 - (uiop->uio_offset % 4096), tsiz);
+ len = min(len, conn->buffer_size);
+ error = ncp_rq_alloc(72, conn, uiop->uio_procp, cred, &rqp);
+ if (error)
+ break;
+ mbp = &rqp->rq;
+ mb_put_uint8(mbp, 0);
+ mb_put_mem(mbp, (caddr_t)file, 6, MB_MSYSTEM);
+ mb_put_uint32be(mbp, uiop->uio_offset);
+ mb_put_uint16be(mbp, len);
+ rqp->nr_minrplen = 2;
+ error = ncp_request(rqp);
+ if (error)
+ break;
+ md_get_uint16be(&rqp->rp, &retlen);
+ if (uiop->uio_offset & 1)
+ md_get_mem(&rqp->rp, NULL, 1, MB_MSYSTEM);
+ error = md_get_uio(&rqp->rp, uiop, retlen);
+ ncp_rq_done(rqp);
+ } else {
+#ifdef NCPBURST
+ error = ncp_burst_read(conn, file, tsiz, &len, &retlen, uiop, cred);
+#endif
+ }
+ if (error)
+ break;
+ tsiz -= retlen;
+ if (retlen < len)
+ break;
}
- ncp_sock_disconnect(conn);
- ncp_conn_free(conn);
- return 0;
+ return (error);
}
-void
-ncp_check_rq(struct ncp_conn *conn){
- return;
- if (conn->flags & NCPFL_INTR) return;
- /* first, check for signals */
- if (ncp_chkintr(conn,conn->procp)) {
- conn->flags |= NCPFL_INTR;
+int
+ncp_write(struct ncp_conn *conn, ncp_fh *file, struct uio *uiop, struct ucred *cred)
+{
+ struct ncp_rq *rqp;
+ struct mbchain *mbp;
+ int error = 0, len, tsiz, backup;
+
+ if (uiop->uio_iovcnt != 1) {
+ printf("%s: can't handle iovcnt>1 !!!\n", __FUNCTION__);
+ return EIO;
}
- return;
+ tsiz = uiop->uio_resid;
+ while (tsiz > 0) {
+ len = min(4096 - (uiop->uio_offset % 4096), tsiz);
+ len = min(len, conn->buffer_size);
+ if (len == 0) {
+ printf("gotcha!\n");
+ }
+ /* rq head */
+ error = ncp_rq_alloc(73, conn, uiop->uio_procp, cred, &rqp);
+ if (error)
+ break;
+ mbp = &rqp->rq;
+ mb_put_uint8(mbp, 0);
+ mb_put_mem(mbp, (caddr_t)file, 6, MB_MSYSTEM);
+ mb_put_uint32be(mbp, uiop->uio_offset);
+ mb_put_uint16be(mbp, len);
+ error = mb_put_uio(mbp, uiop, len);
+ if (error) {
+ ncp_rq_done(rqp);
+ break;
+ }
+ error = ncp_request(rqp);
+ if (!error)
+ ncp_rq_done(rqp);
+ if (len == 0)
+ break;
+ if (error) {
+ backup = len;
+ uiop->uio_iov->iov_base -= backup;
+ uiop->uio_iov->iov_len += backup;
+ uiop->uio_offset -= backup;
+ uiop->uio_resid += backup;
+ break;
+ }
+ tsiz -= len;
+ }
+ if (error)
+ uiop->uio_resid = tsiz;
+ switch (error) {
+ case NWE_INSUFFICIENT_SPACE:
+ error = ENOSPC;
+ break;
+ }
+ return (error);
}
diff --git a/sys/netncp/ncp_ncp.h b/sys/netncp/ncp_ncp.h
index b43370d..779350b 100644
--- a/sys/netncp/ncp_ncp.h
+++ b/sys/netncp/ncp_ncp.h
@@ -111,13 +111,21 @@ struct ncp_rq;
struct proc;
struct ucred;
-int ncp_request(struct ncp_conn *conn,struct ncp_rq *rqp);
int ncp_ncp_connect(struct ncp_conn *conn);
int ncp_ncp_disconnect(struct ncp_conn *conn);
-int ncp_reconnect(struct ncp_conn *conn);
-int ncp_connect(struct ncp_conn_args *li,struct proc *p, struct ucred *cred,struct ncp_conn **aconn);
-int ncp_disconnect(struct ncp_conn *conn);
int ncp_login(struct ncp_conn *conn, char *user, int objtype, char *password,
- struct proc *p, struct ucred *cred);
+ struct proc *p, struct ucred *cred);
+int ncp_negotiate_buffersize(struct ncp_conn *conn, int size, int *target);
+int ncp_renegotiate_connparam(struct ncp_conn *conn, int buffsize,
+ u_int8_t in_options);
+int ncp_get_bindery_object_id(struct ncp_conn *conn,
+ u_int16_t object_type, char *object_name,
+ struct ncp_bindery_object *target,
+ struct proc *p,struct ucred *cred);
+int ncp_login_object(struct ncp_conn *conn, unsigned char *username,
+ int login_type, unsigned char *password,
+ struct proc *p,struct ucred *cred);
+int ncp_read(struct ncp_conn *conn, ncp_fh *file, struct uio *uiop, struct ucred *cred);
+int ncp_write(struct ncp_conn *conn, ncp_fh *file, struct uio *uiop, struct ucred *cred);
#endif /* _NCP_NCP_H_ */
diff --git a/sys/netncp/ncp_nls.c b/sys/netncp/ncp_nls.c
index 3c7892f..ccbf3cc 100644
--- a/sys/netncp/ncp_nls.c
+++ b/sys/netncp/ncp_nls.c
@@ -237,7 +237,8 @@ ncp_pathcheck(char *s, int len, struct ncp_nlstables *nt, int strict) {
* leave it as is.
*/
void
-ncp_pathcopy(char *src, char *dst, int len, struct ncp_nlstables *nt) {
+ncp_pathcopy(const char *src, char *dst, int len, struct ncp_nlstables *nt)
+{
int donls;
u_char c;
/* char *d = dst, *s = src;*/
diff --git a/sys/netncp/ncp_nls.h b/sys/netncp/ncp_nls.h
index bedc7ca..61d3dcd 100644
--- a/sys/netncp/ncp_nls.h
+++ b/sys/netncp/ncp_nls.h
@@ -81,7 +81,7 @@ extern struct ncp_nlstables ncp_defnls;
void ncp_str_upper(char *name);
void ncp_str_lower(char *name);
-void ncp_pathcopy(char *src, char *dst, int len, struct ncp_nlstables *nt);
+void ncp_pathcopy(const char *src, char *dst, int len, struct ncp_nlstables *nt);
int ncp_pathcheck(char *s, int len, struct ncp_nlstables *nt, int strict);
void ncp_path2unix(char *src, char *dst, int len, struct ncp_nlstables *nt);
diff --git a/sys/netncp/ncp_rq.c b/sys/netncp/ncp_rq.c
index dacdee0..fb53775 100644
--- a/sys/netncp/ncp_rq.c
+++ b/sys/netncp/ncp_rq.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, Boris Popov
+ * Copyright (c) 1999, 2000, 2001 Boris Popov
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,7 +36,10 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/errno.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/mbuf.h>
+#include <sys/poll.h>
#include <sys/uio.h>
#include <netncp/ncp.h>
@@ -44,523 +47,424 @@
#include <netncp/ncp_rq.h>
#include <netncp/ncp_subr.h>
#include <netncp/ncp_ncp.h>
+#include <netncp/ncp_sock.h>
#include <netncp/ncp_nls.h>
+static MALLOC_DEFINE(M_NCPRQ, "NCPRQ", "NCP request");
+
+static int ncp_sign_packet(struct ncp_conn *conn, struct ncp_rq *rqp, int *size);
+
+int
+ncp_rq_alloc_any(u_int32_t ptype, u_int8_t fn, struct ncp_conn *ncp,
+ struct proc *p, struct ucred *cred,
+ struct ncp_rq **rqpp)
+{
+ struct ncp_rq *rqp;
+ int error;
+
+ MALLOC(rqp, struct ncp_rq *, sizeof(*rqp), M_NCPRQ, M_WAITOK);
+ error = ncp_rq_init_any(rqp, ptype, fn, ncp, p, cred);
+ rqp->nr_flags |= NCPR_ALLOCED;
+ if (error) {
+ ncp_rq_done(rqp);
+ return error;
+ }
+ *rqpp = rqp;
+ return 0;
+}
+
+int
+ncp_rq_alloc(u_int8_t fn, struct ncp_conn *ncp,
+ struct proc *p, struct ucred *cred, struct ncp_rq **rqpp)
+{
+ return ncp_rq_alloc_any(NCP_REQUEST, fn, ncp, p, cred, rqpp);
+}
+
int
-ncp_rq_head(struct ncp_rq *rqp, u_int32_t ptype, u_int8_t fn,struct proc *p,
- struct ucred *cred)
+ncp_rq_alloc_subfn(u_int8_t fn, u_int8_t subfn, struct ncp_conn *ncp,
+ struct proc *p, struct ucred *cred, struct ncp_rq **rqpp)
+{
+ struct ncp_rq *rqp;
+ int error;
+
+ error = ncp_rq_alloc_any(NCP_REQUEST, fn, ncp, p, cred, &rqp);
+ if (error)
+ return error;
+ mb_reserve(&rqp->rq, 2);
+ mb_put_uint8(&rqp->rq, subfn);
+ *rqpp = rqp;
+ return 0;
+}
+
+int
+ncp_rq_init_any(struct ncp_rq *rqp, u_int32_t ptype, u_int8_t fn,
+ struct ncp_conn *ncp,
+ struct proc *p, struct ucred *cred)
{
- struct mbuf *m;
struct ncp_rqhdr *rq;
struct ncp_bursthdr *brq;
- caddr_t pstart;
+ struct mbchain *mbp;
+ int error;
bzero(rqp, sizeof(*rqp));
- rqp->p = p;
- rqp->cred = cred;
- m = m_gethdr(M_TRYWAIT, MT_DATA);
- if (m == NULL)
- return ENOBUFS; /* if M_TRYWAIT ? */
- m->m_pkthdr.rcvif = NULL;
- rqp->rq = rqp->mrq = m;
- rqp->rp = NULL;
+ error = ncp_conn_access(ncp, cred, NCPM_EXECUTE);
+ if (error)
+ return error;
+ rqp->nr_p = p;
+ rqp->nr_cred = cred;
+ rqp->nr_conn = ncp;
+ mbp = &rqp->rq;
+ if (mb_init(mbp) != 0)
+ return ENOBUFS;
switch(ptype) {
case NCP_PACKET_BURST:
- MH_ALIGN(m, sizeof(*brq) + 24);
- m->m_len = sizeof(*brq);
- brq = mtod(m, struct ncp_bursthdr *);
+ brq = (struct ncp_bursthdr*)mb_reserve(mbp, sizeof(*brq));
brq->bh_type = ptype;
brq->bh_streamtype = 0x2;
- pstart = (caddr_t)brq;
break;
default:
- MH_ALIGN(m, sizeof(*rq) + 2); /* possible len field in some functions */
- m->m_len = sizeof(*rq);
- rq = mtod(m, struct ncp_rqhdr *);
+ rq = (struct ncp_rqhdr*)mb_reserve(mbp, sizeof(*rq));
rq->type = ptype;
rq->seq = 0; /* filled later */
rq->fn = fn;
- pstart = (caddr_t)rq;
break;
}
- rqp->bpos = pstart + m->m_len;
+ rqp->nr_minrplen = -1;
return 0;
}
-int
-ncp_rq_done(struct ncp_rq *rqp) {
- m_freem(rqp->rq);
- rqp->rq=NULL;
- if (rqp->rp) m_freem(rqp->rp);
- rqp->rp=NULL;
- return (0);
+void
+ncp_rq_done(struct ncp_rq *rqp)
+{
+ mb_done(&rqp->rq);
+ md_done(&rqp->rp);
+ if (rqp->nr_flags & NCPR_ALLOCED)
+ free(rqp, M_NCPRQ);
+ return;
}
/*
* Routines to fill the request
*/
-static caddr_t ncp_mchecksize(struct ncp_rq *rqp, int size);
-#define NCP_RQADD(t) ((t*)(ncp_mchecksize(rqp,sizeof(t))))
-
-caddr_t
-ncp_mchecksize(struct ncp_rq *rqp, int size) {
- caddr_t bpos1;
-
- if (size>MLEN)
- panic("ncp_mchecksize\n");
- if (M_TRAILINGSPACE(rqp->mrq)<(size)) {
- struct mbuf *m;
- m = m_get(M_TRYWAIT, MT_DATA);
- m->m_len = 0;
- rqp->bpos = mtod(m, caddr_t);
- rqp->mrq->m_next = m;
- rqp->mrq = m;
- }
- rqp->mrq->m_len += size;
- bpos1 = rqp->bpos;
- rqp->bpos += size;
- return bpos1;
-}
-
-void
-ncp_rq_byte(struct ncp_rq *rqp,u_int8_t x) {
- *NCP_RQADD(u_int8_t)=x;
-}
-
-void
-ncp_rq_word_hl(struct ncp_rq *rqp, u_int16_t x) {
- setwbe(NCP_RQADD(u_int16_t), 0, x);
-}
-
-void
-ncp_rq_word_lh(struct ncp_rq *rqp, u_int16_t x) {
- setwle(NCP_RQADD(u_int16_t), 0, x);
-}
-void
-ncp_rq_dword_lh(struct ncp_rq *rqp, u_int32_t x) {
- setdle(NCP_RQADD(u_int32_t), 0, x);
-}
-
-void
-ncp_rq_pathstring(struct ncp_rq *rqp, int size, char *name, struct ncp_nlstables *nt) {
- struct mbuf *m;
- int cplen;
-
- ncp_rq_byte(rqp, size);
- m = rqp->mrq;
- cplen = min(size, M_TRAILINGSPACE(m));
- if (cplen) {
- ncp_pathcopy(name, rqp->bpos, cplen, nt);
- size -= cplen;
- name += cplen;
- m->m_len += cplen;
- }
- if (size) {
- m = m_getm(m, size, MT_DATA, M_TRYWAIT);
- while (size > 0){
- m = m->m_next;
- cplen = min(size, M_TRAILINGSPACE(m));
- ncp_pathcopy(name, mtod(m, caddr_t) + m->m_len, cplen, nt);
- size -= cplen;
- name += cplen;
- m->m_len += cplen;
- }
- }
- rqp->bpos = mtod(m,caddr_t) + m->m_len;
- rqp->mrq = m;
- return;
-}
-
-int
-ncp_rq_putanymem(struct ncp_rq *rqp, caddr_t source, int size, int type) {
- struct mbuf *m;
- int cplen, error;
-
- m = rqp->mrq;
- cplen = min(size, M_TRAILINGSPACE(m));
- if (cplen) {
- if (type==1) {
- error = copyin(source, rqp->bpos, cplen);
- if (error) return error;
- } else
- bcopy(source, rqp->bpos, cplen);
- size -= cplen;
- source += cplen;
- m->m_len += cplen;
- }
- if (size) {
- m = m_getm(m, size, MT_DATA, M_TRYWAIT);
- while (size > 0){
- m = m->m_next;
- cplen = min(size, M_TRAILINGSPACE(m));
- if (type==1) {
- error = copyin(source, mtod(m, caddr_t) + m->m_len, cplen);
- if (error) return error;
- } else
- bcopy(source, mtod(m, caddr_t) + m->m_len, cplen);
- size -= cplen;
- source += cplen;
- m->m_len += cplen;
- }
- }
- rqp->bpos = mtod(m,caddr_t) + m->m_len;
- rqp->mrq = m;
+static int
+ncp_rq_pathstrhelp(struct mbchain *mbp, c_caddr_t src, caddr_t dst, int len)
+{
+ ncp_pathcopy(src, dst, len, mbp->mb_udata);
return 0;
}
int
-ncp_rq_mbuf(struct ncp_rq *rqp, struct mbuf *m, int size) {
+ncp_rq_pathstring(struct ncp_rq *rqp, int size, const char *name,
+ struct ncp_nlstables *nt)
+{
+ struct mbchain *mbp = &rqp->rq;
- rqp->mrq->m_next = m;
- m->m_next = NULL;
- if (size != M_COPYALL) m->m_len = size;
- rqp->bpos = mtod(m,caddr_t) + m->m_len;
- rqp->mrq = m;
- return 0;
+ mb_put_uint8(mbp, size);
+ mbp->mb_copy = ncp_rq_pathstrhelp;
+ mbp->mb_udata = nt;
+ return mb_put_mem(mbp, (c_caddr_t)name, size, MB_MCUSTOM);
}
-void
-ncp_rq_pstring(struct ncp_rq *rqp, char *s) {
- int len = strlen(s);
- if (len > 255) {
- nwfs_printf("string too long: %s\n", s);
- len = 255;
- }
- ncp_rq_byte(rqp, len);
- ncp_rq_mem(rqp, s, len);
- return;
+int
+ncp_rq_pstring(struct ncp_rq *rqp, const char *s)
+{
+ u_int len = strlen(s);
+ int error;
+
+ if (len > 255)
+ return EINVAL;
+ error = mb_put_uint8(&rqp->rq, len);
+ if (error)
+ return error;
+ return mb_put_mem(&rqp->rq, s, len, MB_MSYSTEM);
}
-void
+int
ncp_rq_dbase_path(struct ncp_rq *rqp, u_int8_t vol_num, u_int32_t dir_base,
int namelen, u_char *path, struct ncp_nlstables *nt)
{
+ struct mbchain *mbp = &rqp->rq;
int complen;
- ncp_rq_byte(rqp, vol_num);
- ncp_rq_dword(rqp, dir_base);
- ncp_rq_byte(rqp, 1); /* with dirbase */
+ mb_put_uint8(mbp, vol_num);
+ mb_put_mem(mbp, (c_caddr_t)&dir_base, sizeof(dir_base), MB_MSYSTEM);
+ mb_put_uint8(mbp, 1); /* with dirbase */
if (path != NULL && path[0]) {
if (namelen < 0) {
namelen = *path++;
- ncp_rq_byte(rqp, namelen);
+ mb_put_uint8(mbp, namelen);
for(; namelen; namelen--) {
complen = *path++;
- ncp_rq_byte(rqp, complen);
- ncp_rq_mem(rqp, path, complen);
+ mb_put_uint8(mbp, complen);
+ mb_put_mem(mbp, path, complen, MB_MSYSTEM);
path += complen;
}
} else {
- ncp_rq_byte(rqp, 1); /* 1 component */
+ mb_put_uint8(mbp, 1); /* 1 component */
ncp_rq_pathstring(rqp, namelen, path, nt);
}
} else {
- ncp_rq_byte(rqp, 0);
- ncp_rq_byte(rqp, 0);
+ mb_put_uint8(mbp, 0);
+ mb_put_uint8(mbp, 0);
}
+ return 0;
}
-/*
- * fetch reply routines
+
+/*
+ * Make a signature for the current packet and add it at the end of the
+ * packet.
*/
-#define ncp_mspaceleft (mtod(rqp->mrp,caddr_t)+rqp->mrp->m_len-rqp->bpos)
+static int
+ncp_sign_packet(struct ncp_conn *conn, struct ncp_rq *rqp, int *size)
+{
+ u_char data[64];
+ int error;
-u_int8_t
-ncp_rp_byte(struct ncp_rq *rqp) {
- if (rqp->mrp == NULL) return 0;
- if (ncp_mspaceleft < 1) {
- rqp->mrp = rqp->mrp->m_next;
- if (rqp->mrp == NULL) return 0;
- rqp->bpos = mtod(rqp->mrp, caddr_t);
- }
- rqp->bpos += 1;
- return rqp->bpos[-1];
+ bzero(data, sizeof(data));
+ bcopy(conn->sign_root, data, 8);
+ setdle(data, 8, *size);
+ m_copydata(rqp->rq.mb_top, sizeof(struct ncp_rqhdr) - 1,
+ min((*size) - sizeof(struct ncp_rqhdr)+1, 52), data + 12);
+ ncp_sign(conn->sign_state, data, conn->sign_state);
+ error = mb_put_mem(&rqp->rq, (caddr_t)conn->sign_state, 8, MB_MSYSTEM);
+ if (error)
+ return error;
+ (*size) += 8;
+ return 0;
}
-u_int16_t
-ncp_rp_word_lh(struct ncp_rq *rqp) {
- caddr_t prev = rqp->bpos;
- u_int16_t t;
-
- if (rqp->mrp == NULL) return 0;
- if (ncp_mspaceleft >= 2) {
- rqp->bpos += 2;
- return getwle(prev,0);
+/*
+ * Low level send rpc, here we do not attempt to restore any connection,
+ * Connection expected to be locked
+ */
+int
+ncp_request_int(struct ncp_rq *rqp)
+{
+ struct ncp_conn *conn = rqp->nr_conn;
+ struct proc *p = conn->procp;
+ struct socket *so = conn->ncp_so;
+ struct ncp_rqhdr *rq;
+ struct ncp_rphdr *rp=NULL;
+ struct timeval tv;
+ struct mbuf *m, *mreply = NULL;
+ struct mbchain *mbp;
+ int error, len, dosend, plen = 0, gotpacket;
+
+ if (conn->flags & NCPFL_INVALID)
+ return ENOTCONN;
+ if (so == NULL) {
+ printf("%s: ncp_so is NULL !\n",__FUNCTION__);
+ conn->flags |= NCPFL_INVALID;
+ return ENOTCONN;
}
- t = *((u_int8_t*)(rqp->bpos));
- rqp->mrp = rqp->mrp->m_next;
- if (rqp->mrp == NULL) return 0;
- ((u_int8_t *)&t)[1] = *((u_int8_t*)(rqp->bpos = mtod(rqp->mrp, caddr_t)));
- rqp->bpos += 2;
- return t;
-}
-
-u_int16_t
-ncp_rp_word_hl(struct ncp_rq *rqp) {
- return (ntohs(ncp_rp_word_lh(rqp)));
-}
-
-u_int32_t
-ncp_rp_dword_hl(struct ncp_rq *rqp) {
- int togo, rest;
- caddr_t prev = rqp->bpos;
- u_int32_t t;
-
- if (rqp->mrp == NULL) return 0;
- rest = ncp_mspaceleft;
- if (rest >= 4) {
- rqp->bpos += 4;
- return getdbe(prev,0);
+ if (p == NULL)
+ p = curproc; /* XXX maybe procpage ? */
+ /*
+ * Flush out replies on previous reqs
+ */
+ while (ncp_poll(so, POLLIN) != 0) {
+ if (ncp_sock_recv(so, &m, &len) != 0)
+ break;
+ m_freem(m);
}
- togo = 0;
- while (rest--) {
- ((u_int8_t *)&t)[togo++] = *((u_int8_t*)(prev++));
+ mbp = &rqp->rq;
+ len = mb_fixhdr(mbp);
+ rq = mtod(mbp->mb_top, struct ncp_rqhdr *);
+ rq->seq = conn->seq;
+ m = rqp->rq.mb_top;
+
+ switch (rq->fn) {
+ case 0x15: case 0x16: case 0x17: case 0x23:
+ *(u_int16_t*)(rq + 1) = htons(len - 2 - sizeof(*rq));
+ break;
}
- rqp->mrp = rqp->mrp->m_next;
- if (rqp->mrp == NULL) return 0;
- prev = mtod(rqp->mrp, caddr_t);
- rqp->bpos = prev + 4 - togo; /* XXX possible low than togo bytes in next mbuf */
- while (togo < 4) {
- ((u_int8_t *)&t)[togo++] = *((u_int8_t*)(prev++));
+ if (conn->flags & NCPFL_SIGNACTIVE) {
+ error = ncp_sign_packet(conn, rqp, &len);
+ if (error)
+ return error;
+ mbp->mb_top->m_pkthdr.len = len;
}
- return getdbe(&t,0);
-}
-
-u_int32_t
-ncp_rp_dword_lh(struct ncp_rq *rqp) {
- int rest, togo;
- caddr_t prev = rqp->bpos;
- u_int32_t t;
-
- if (rqp->mrp == NULL) return 0;
- rest = ncp_mspaceleft;
- if (rest >= 4) {
- rqp->bpos += 4;
- return getdle(prev,0);
+ rq->conn_low = conn->connid & 0xff;
+ /* rq->task = p->p_pgrp->pg_id & 0xff; */ /*p->p_pid*/
+ /* XXX: this is temporary fix till I find a better solution */
+ rq->task = rq->conn_low;
+ rq->conn_high = conn->connid >> 8;
+ rqp->rexmit = conn->li.retry_count;
+ error = 0;
+ for(dosend = 1;;) {
+ if (rqp->rexmit-- == 0) {
+ error = ETIMEDOUT;
+ break;
+ }
+ error = 0;
+ if (dosend) {
+ NCPSDEBUG("send:%04x f=%02x c=%d l=%d s=%d t=%d\n",rq->type, rq->fn, (rq->conn_high << 8) + rq->conn_low,
+ mbp->mb_top->m_pkthdr.len, rq->seq, rq->task
+ );
+ error = ncp_sock_send(so, mbp->mb_top, rqp);
+ if (error)
+ break;
+ }
+ tv.tv_sec = conn->li.timeout;
+ tv.tv_usec = 0;
+ error = ncp_sock_rselect(so, p, &tv, POLLIN);
+ if (error == EWOULDBLOCK ) /* timeout expired */
+ continue;
+ error = ncp_chkintr(conn, p);
+ if (error)
+ break;
+ /*
+ * At this point it is possible to get more than one
+ * reply from server. In general, last reply should be for
+ * current request, but not always. So, we loop through
+ * all replies to find the right answer and flush others.
+ */
+ gotpacket = 0; /* nothing good found */
+ dosend = 1; /* resend rq if error */
+ for (;;) {
+ error = 0;
+ if (ncp_poll(so, POLLIN) == 0)
+ break;
+/* if (so->so_rcv.sb_cc == 0) {
+ break;
+ }*/
+ error = ncp_sock_recv(so, &m, &len);
+ if (error)
+ break; /* must be more checks !!! */
+ if (m->m_len < sizeof(*rp)) {
+ m = m_pullup(m, sizeof(*rp));
+ if (m == NULL) {
+ printf("%s: reply too short\n",__FUNCTION__);
+ continue;
+ }
+ }
+ rp = mtod(m, struct ncp_rphdr*);
+ if (len == sizeof(*rp) && rp->type == NCP_POSITIVE_ACK) {
+ NCPSDEBUG("got positive acknowledge\n");
+ m_freem(m);
+ rqp->rexmit = conn->li.retry_count;
+ dosend = 0; /* server just busy and will reply ASAP */
+ continue;
+ }
+ NCPSDEBUG("recv:%04x c=%d l=%d s=%d t=%d cc=%02x cs=%02x\n",rp->type,
+ (rp->conn_high << 8) + rp->conn_low, len, rp->seq, rp->task,
+ rp->completion_code, rp->connection_state);
+ NCPDDEBUG(m);
+ if ( (rp->type == NCP_REPLY) &&
+ ((rq->type == NCP_ALLOC_SLOT) ||
+ ((rp->conn_low == rq->conn_low) &&
+ (rp->conn_high == rq->conn_high)
+ ))) {
+ if (rq->seq > rp->seq || (rq->seq == 0 && rp->seq == 0xff)) {
+ dosend = 1;
+ }
+ if (rp->seq == rq->seq) {
+ if (gotpacket) {
+ m_freem(m);
+ } else {
+ gotpacket = 1;
+ mreply = m;
+ plen = len;
+ }
+ continue; /* look up other for other packets */
+ }
+ }
+ m_freem(m);
+ NCPSDEBUG("reply mismatch\n");
+ } /* for receive */
+ if (error || gotpacket)
+ break;
+ /* try to resend, or just wait */
}
- togo = 0;
- while (rest--) {
- ((u_int8_t *)&t)[togo++] = *((u_int8_t*)(prev++));
+ conn->seq++;
+ if (error) {
+ NCPSDEBUG("error=%d\n", error);
+ /*
+ * Any error except interruped call means that we have
+ * to reconnect. So, eliminate future timeouts by invalidating
+ * connection now.
+ */
+ if (error != EINTR)
+ conn->flags |= NCPFL_INVALID;
+ return (error);
}
- rqp->mrp = rqp->mrp->m_next;
- if (rqp->mrp == NULL) return 0;
- prev = mtod(rqp->mrp, caddr_t);
- rqp->bpos = prev + 4 - togo; /* XXX possible low than togo bytes in next mbuf */
- while (togo < 4) {
- ((u_int8_t *)&t)[togo++] = *((u_int8_t*)(prev++));
+ if (conn->flags & NCPFL_SIGNACTIVE) {
+ /* XXX: check reply signature */
+ m_adj(mreply, -8);
+ plen -= 8;
}
- return getdle(&t,0);
-}
-void
-ncp_rp_mem(struct ncp_rq *rqp,caddr_t target, int size) {
- register struct mbuf *m=rqp->mrp;
- register unsigned count;
-
- while (size > 0) {
- if (m==0) { /* should be panic */
- printf("ncp_rp_mem: incomplete copy\n");
- return;
- }
- count = mtod(m,caddr_t)+m->m_len-rqp->bpos;
- if (count == 0) {
- m=m->m_next;
- rqp->bpos=mtod(m,caddr_t);
- continue;
- }
- count = min(count,size);
- bcopy(rqp->bpos, target, count);
- size -= count;
- target += count;
- rqp->bpos += count;
+ rp = mtod(mreply, struct ncp_rphdr*);
+ md_initm(&rqp->rp, mreply);
+ rqp->nr_rpsize = plen - sizeof(*rp);
+ rqp->nr_cc = error = rp->completion_code;
+ if (error)
+ error |= 0x8900; /* server error */
+ rqp->nr_cs = rp->connection_state;
+ if (rqp->nr_cs & (NCP_CS_BAD_CONN | NCP_CS_SERVER_DOWN)) {
+ NCPSDEBUG("server drop us\n");
+ conn->flags |= NCPFL_INVALID;
+ error = ECONNRESET;
}
- rqp->mrp=m;
- return;
+ md_get_mem(&rqp->rp, NULL, sizeof(*rp), MB_MSYSTEM);
+ return error;
}
-int
-ncp_rp_usermem(struct ncp_rq *rqp,caddr_t target, int size) {
- register struct mbuf *m=rqp->mrp;
- register unsigned count;
+/*
+ * Here we will try to restore any loggedin & dropped connection,
+ * connection should be locked on entry
+ */
+static __inline int
+ncp_restore_login(struct ncp_conn *conn)
+{
int error;
-
- while (size>0) {
- if (m==0) { /* should be panic */
- printf("ncp_rp_mem: incomplete copy\n");
- return EFAULT;
- }
- count = mtod(m,caddr_t)+m->m_len-rqp->bpos;
- if (count == 0) {
- m=m->m_next;
- rqp->bpos=mtod(m,caddr_t);
- continue;
- }
- count = min(count,size);
- error=copyout(rqp->bpos, target, count);
- if (error) return error;
- size -= count;
- target += count;
- rqp->bpos += count;
- }
- rqp->mrp=m;
- return 0;
-}
-struct mbuf*
-ncp_rp_mbuf(struct ncp_rq *rqp, int size) {
- register struct mbuf *m=rqp->mrp, *rm;
- register unsigned count;
-
- rm = m_copym(m, rqp->bpos - mtod(m,caddr_t), size, M_TRYWAIT);
- while (size > 0) {
- if (m == 0) {
- printf("ncp_rp_mbuf: can't advance\n");
- return rm;
- }
- count = mtod(m,caddr_t)+ m->m_len - rqp->bpos;
- if (count == 0) {
- m = m->m_next;
- rqp->bpos = mtod(m, caddr_t);
- continue;
- }
- count = min(count, size);
- size -= count;
- rqp->bpos += count;
- }
- rqp->mrp=m;
- return rm;
+ printf("ncprq: Restoring connection, flags = %x\n", conn->flags);
+ conn->flags &= ~(NCPFL_LOGGED | NCPFL_ATTACHED);
+ conn->flags |= NCPFL_RESTORING;
+ error = ncp_conn_reconnect(conn);
+ if (!error && (conn->flags & NCPFL_WASLOGGED))
+ error = ncp_login_object(conn, conn->li.user, conn->li.objtype, conn->li.password,conn->procp,conn->ucred);
+ if (error)
+ conn->flags |= NCPFL_INVALID;
+ conn->flags &= ~NCPFL_RESTORING;
+ return error;
}
int
-nwfs_mbuftouio(mrep, uiop, siz, dpos)
- struct mbuf **mrep;
- register struct uio *uiop;
- int siz;
- caddr_t *dpos;
+ncp_request(struct ncp_rq *rqp)
{
- register char *mbufcp, *uiocp;
- register int xfer, left, len;
- register struct mbuf *mp;
- long uiosiz;
- int error = 0;
-
- mp = *mrep;
- if (!mp) return 0;
- mbufcp = *dpos;
- len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
- while (siz > 0) {
- if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
- return (EFBIG);
- left = uiop->uio_iov->iov_len;
- uiocp = uiop->uio_iov->iov_base;
- if (left > siz)
- left = siz;
- uiosiz = left;
- while (left > 0) {
- while (len == 0) {
- mp = mp->m_next;
- if (mp == NULL)
- return (EBADRPC);
- mbufcp = mtod(mp, caddr_t);
- len = mp->m_len;
- }
- xfer = (left > len) ? len : left;
-#ifdef notdef
- /* Not Yet.. */
- if (uiop->uio_iov->iov_op != NULL)
- (*(uiop->uio_iov->iov_op))
- (mbufcp, uiocp, xfer);
- else
-#endif
- if (uiop->uio_segflg == UIO_SYSSPACE)
- bcopy(mbufcp, uiocp, xfer);
- else
- copyout(mbufcp, uiocp, xfer);
- left -= xfer;
- len -= xfer;
- mbufcp += xfer;
- uiocp += xfer;
- uiop->uio_offset += xfer;
- uiop->uio_resid -= xfer;
+ struct ncp_conn *ncp = rqp->nr_conn;
+ int error, rcnt;
+
+ error = ncp_conn_lock(ncp, rqp->nr_p, rqp->nr_cred, NCPM_EXECUTE);
+ if (error)
+ goto out;
+ rcnt = NCP_RESTORE_COUNT;
+ for(;;) {
+ if ((ncp->flags & NCPFL_INVALID) == 0) {
+ error = ncp_request_int(rqp);
+ if ((ncp->flags & NCPFL_INVALID) == 0)
+ break;
}
- if (uiop->uio_iov->iov_len <= siz) {
- uiop->uio_iovcnt--;
- uiop->uio_iov++;
- } else {
- uiop->uio_iov->iov_base += uiosiz;
- uiop->uio_iov->iov_len -= uiosiz;
+ if (rcnt-- == 0) {
+ error = ECONNRESET;
+ break;
}
- siz -= uiosiz;
- }
- *dpos = mbufcp;
- *mrep = mp;
- return (error);
-}
-/*
- * copies a uio scatter/gather list to an mbuf chain.
- * NOTE: can ony handle iovcnt == 1
- */
-int
-nwfs_uiotombuf(uiop, mq, siz, bpos)
- register struct uio *uiop;
- struct mbuf **mq;
- int siz;
- caddr_t *bpos;
-{
- register char *uiocp;
- register struct mbuf *mp, *mp2;
- register int xfer, left, mlen;
- int uiosiz, clflg;
-
-#ifdef DIAGNOSTIC
- if (uiop->uio_iovcnt != 1)
- panic("nfsm_uiotombuf: iovcnt != 1");
-#endif
-
- if (siz > MLEN) /* or should it >= MCLBYTES ?? */
- clflg = 1;
- else
- clflg = 0;
- mp = mp2 = *mq;
- while (siz > 0) {
- left = uiop->uio_iov->iov_len;
- uiocp = uiop->uio_iov->iov_base;
- if (left > siz)
- left = siz;
- uiosiz = left;
- while (left > 0) {
- mlen = M_TRAILINGSPACE(mp);
- if (mlen == 0) {
- MGET(mp, M_TRYWAIT, MT_DATA);
- if (clflg)
- MCLGET(mp, M_TRYWAIT);
- mp->m_len = 0;
- mp2->m_next = mp;
- mp2 = mp;
- mlen = M_TRAILINGSPACE(mp);
- }
- xfer = (left > mlen) ? mlen : left;
-#ifdef notdef
- /* Not Yet.. */
- if (uiop->uio_iov->iov_op != NULL)
- (*(uiop->uio_iov->iov_op))
- (uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
- else
-#endif
- if (uiop->uio_segflg == UIO_SYSSPACE)
- bcopy(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
- else
- copyin(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
- mp->m_len += xfer;
- left -= xfer;
- uiocp += xfer;
- uiop->uio_offset += xfer;
- uiop->uio_resid -= xfer;
+ /*
+ * Do not attempt to restore connection recursively
+ */
+ if (ncp->flags & NCPFL_RESTORING) {
+ error = ENOTCONN;
+ break;
}
- uiop->uio_iov->iov_base += uiosiz;
- uiop->uio_iov->iov_len -= uiosiz;
- siz -= uiosiz;
+ error = ncp_restore_login(ncp);
+ if (error)
+ continue;
}
- *bpos = mtod(mp, caddr_t)+mp->m_len;
- *mq = mp;
- return (0);
+ ncp_conn_unlock(ncp, rqp->nr_p);
+out:
+ if (error && (rqp->nr_flags & NCPR_DONTFREEONERR) == 0)
+ ncp_rq_done(rqp);
+ return error;
}
diff --git a/sys/netncp/ncp_rq.h b/sys/netncp/ncp_rq.h
index 7c90e9f..bff912d 100644
--- a/sys/netncp/ncp_rq.h
+++ b/sys/netncp/ncp_rq.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, Boris Popov
+ * Copyright (c) 1999, 2000, 2001 Boris Popov
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -82,76 +82,49 @@
#ifdef _KERNEL
-struct ncp_nlstables;
+
+#include <sys/mchain.h>
+
+#define NCPR_ALLOCED 0x0001 /* request structure was allocated */
+#define NCPR_DONTFREEONERR 0x0002 /* do not free structure on error */
+
/*
* Structure to prepare ncp request and receive reply
*/
struct ncp_rq {
- struct ncp_conn *conn; /* back link */
- struct mbuf *rq;
- struct mbuf *mrq;
- struct mbuf *rp;
- struct mbuf *mrp;
- caddr_t bpos;
-/* int rqsize;*/ /* request size without ncp header */
- int rpsize; /* reply size minus ncp header */
- int cc; /* completion code */
- int cs; /* connection state */
- struct proc *p; /* proc that did rq */
- struct ucred *cred; /* user that did rq */
+ int nr_flags;
+ struct mbchain rq;
+ struct mdchain rp;
+ int nr_minrplen; /* minimal rp size (-1 if not known) */
+ int nr_rpsize; /* reply size minus ncp header */
+ int nr_cc; /* completion code */
+ int nr_cs; /* connection state */
+ struct proc * nr_p; /* proc that did rq */
+ struct ucred * nr_cred; /* user that did rq */
int rexmit;
+ struct ncp_conn*nr_conn; /* back link */
};
-#define DECLARE_RQ struct ncp_rq rq;struct ncp_rq *rqp=&rq
-
-
-int ncp_rq_head(struct ncp_rq *rqp,u_int32_t ptype, u_int8_t fn,struct proc *p,
- struct ucred *cred);
-int ncp_rq_done(struct ncp_rq *rqp);
-
-/* common case for normal request */
-#define ncp_rq_init(rqp,fn,p,c) ncp_rq_head((rqp),NCP_REQUEST,(fn),(p),(c))
-#define ncp_rq_close(rqp) ncp_rq_done((rqp))
-
-#define NCP_RQ_HEAD(fn,p,c) ncp_rq_init(rqp,fn,p,c)
-#define NCP_RQ_HEAD_S(fn,sfn,p,c) NCP_RQ_HEAD(fn,p,c);ncp_rq_word(rqp,0);ncp_rq_byte(rqp,(sfn))
-#define NCP_RQ_EXIT bad: ncp_rq_close(rqp)
-#define NCP_RQ_EXIT_NB ncp_rq_close(rqp)
-#define ncp_rq_word ncp_rq_word_lh
-#define ncp_rq_dword ncp_rq_dword_lh
-
-/*void ncp_init_request(struct ncp_rq *rqp, int fn);
-void ncp_close_request(struct ncp_rq *rqp);*/
-void ncp_rq_byte(struct ncp_rq *rqp, u_int8_t x);
-void ncp_rq_word_hl(struct ncp_rq *rqp, u_int16_t x);
-void ncp_rq_word_lh(struct ncp_rq *rqp, u_int16_t x);
-void ncp_rq_dword_lh(struct ncp_rq *rqp, u_int32_t x);
-static void ncp_rq_mem(struct ncp_rq *rqp, caddr_t source, int size);
-static int ncp_rq_usermem(struct ncp_rq *rqp, caddr_t source, int size);
-int ncp_rq_mbuf(struct ncp_rq *rqp, struct mbuf *m, int size);
-int ncp_rq_putanymem(struct ncp_rq *rqp, caddr_t source, int size,int type);
-void ncp_rq_pathstring(struct ncp_rq *rqp, int size, char *name, struct ncp_nlstables*);
-void ncp_rq_dbase_path(struct ncp_rq *, u_int8_t vol_num,
+int ncp_rq_alloc(u_int8_t fn, struct ncp_conn *ncp, struct proc *p,
+ struct ucred *cred, struct ncp_rq **rqpp);
+int ncp_rq_alloc_any(u_int32_t ptype, u_int8_t fn, struct ncp_conn *ncp,
+ struct proc *p, struct ucred *cred, struct ncp_rq **rqpp);
+int ncp_rq_alloc_subfn(u_int8_t fn, u_int8_t subfn, struct ncp_conn *ncp,
+ struct proc *p, struct ucred *cred, struct ncp_rq **rqpp);
+int ncp_rq_init_any(struct ncp_rq *rqp, u_int32_t ptype, u_int8_t fn,
+ struct ncp_conn *ncp,
+ struct proc *p, struct ucred *cred);
+void ncp_rq_done(struct ncp_rq *rqp);
+int ncp_request(struct ncp_rq *rqp);
+int ncp_request_int(struct ncp_rq *rqp);
+
+struct ncp_nlstables;
+
+int ncp_rq_pathstring(struct ncp_rq *rqp, int size, const char *name, struct ncp_nlstables*);
+int ncp_rq_dbase_path(struct ncp_rq *, u_int8_t vol_num,
u_int32_t dir_base, int namelen, u_char *name, struct ncp_nlstables *nt);
-void ncp_rq_pstring(struct ncp_rq *rqp, char *s);
-
-u_int8_t ncp_rp_byte(struct ncp_rq *rqp);
-u_int16_t ncp_rp_word_hl(struct ncp_rq *rqp);
-u_int16_t ncp_rp_word_lh(struct ncp_rq *rqp);
-u_int32_t ncp_rp_dword_hl(struct ncp_rq *rqp);
-u_int32_t ncp_rp_dword_lh(struct ncp_rq *rqp);
-void ncp_rp_mem(struct ncp_rq *rqp,caddr_t target, int size);
-int ncp_rp_usermem(struct ncp_rq *rqp,caddr_t target, int size);
-int nwfs_mbuftouio(struct mbuf **mrep, struct uio *uiop, int siz, caddr_t *dpos);
-int nwfs_uiotombuf(struct uio *uiop, struct mbuf **mq, int siz, caddr_t *bpos);
-struct mbuf* ncp_rp_mbuf(struct ncp_rq *rqp, int size);
-
-static void __inline ncp_rq_mem(struct ncp_rq *rqp, caddr_t source, int size) {
- ncp_rq_putanymem(rqp,source,size,0);
-}
-static int __inline ncp_rq_usermem(struct ncp_rq *rqp, caddr_t source, int size) {
- return ncp_rq_putanymem(rqp,source,size,1);
-}
+int ncp_rq_pstring(struct ncp_rq *rqp, const char *s);
+
void ncp_sign_init(const char *logindata, char *sign_root);
#else /* ifdef _KERNEL */
diff --git a/sys/netncp/ncp_sock.c b/sys/netncp/ncp_sock.c
index 206c341..6503c2b 100644
--- a/sys/netncp/ncp_sock.c
+++ b/sys/netncp/ncp_sock.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, Boris Popov
+ * Copyright (c) 1999, 2001 Boris Popov
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,13 +34,6 @@
* Low level socket routines
*/
-#include "opt_inet.h"
-#include "opt_ipx.h"
-
-#if !defined(INET) && !defined(IPX)
-#error "NCP requeires either INET of IPX protocol family"
-#endif
-
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/malloc.h>
@@ -55,10 +48,8 @@
#include <sys/mbuf.h>
#include <net/route.h>
-#ifdef IPX
#include <netipx/ipx.h>
#include <netipx/ipx_pcb.h>
-#endif
#include <netncp/ncp.h>
#include <netncp/ncp_conn.h>
@@ -66,11 +57,9 @@
#include <netncp/ncp_subr.h>
#include <netncp/ncp_rq.h>
-#ifdef IPX
#define ipx_setnullnet(x) ((x).x_net.s_net[0]=0); ((x).x_net.s_net[1]=0);
#define ipx_setnullhost(x) ((x).x_host.s_host[0] = 0); \
((x).x_host.s_host[1] = 0); ((x).x_host.s_host[2] = 0);
-#endif
/*int ncp_poll(struct socket *so, int events);*/
/*static int ncp_getsockname(struct socket *so, caddr_t asa, int *alen);*/
@@ -165,7 +154,7 @@ ncp_sock_send(struct socket *so, struct mbuf *top, struct ncp_rq *rqp)
{
struct proc *p = curproc; /* XXX */
struct sockaddr *to = 0;
- struct ncp_conn *conn = rqp->conn;
+ struct ncp_conn *conn = rqp->nr_conn;
struct mbuf *m;
int error, flags=0;
int sendwait;
@@ -243,12 +232,12 @@ done:
return (error);
}
-#ifdef IPX
/*
* Connect to specified server via IPX
*/
-int
-ncp_sock_connect_ipx(struct ncp_conn *conn) {
+static int
+ncp_sock_connect_ipx(struct ncp_conn *conn)
+{
struct sockaddr_ipx sipx;
struct ipxpcb *npcb;
struct proc *p = conn->procp;
@@ -319,25 +308,23 @@ bad:
}
int
-ncp_sock_checksum(struct ncp_conn *conn, int enable) {
+ncp_sock_checksum(struct ncp_conn *conn, int enable)
+{
-#ifdef SO_IPX_CHECKSUM
if (enable) {
sotoipxpcb(conn->ncp_so)->ipxp_flags |= IPXP_CHECKSUM;
} else {
sotoipxpcb(conn->ncp_so)->ipxp_flags &= ~IPXP_CHECKSUM;
}
-#endif
return 0;
}
-#endif
-#ifdef INET
/*
* Connect to specified server via IP
*/
-int
-ncp_sock_connect_in(struct ncp_conn *conn) {
+static int
+ncp_sock_connect_in(struct ncp_conn *conn)
+{
struct sockaddr_in sin;
struct proc *p=conn->procp;
int addrlen=sizeof(sin), error;
@@ -357,8 +344,24 @@ bad:
ncp_sock_disconnect(conn);
return (error);
}
-#endif
+int
+ncp_sock_connect(struct ncp_conn *ncp)
+{
+ int error;
+
+ switch (ncp->li.saddr.sa_family) {
+ case AF_IPX:
+ error = ncp_sock_connect_ipx(ncp);
+ break;
+ case AF_INET:
+ error = ncp_sock_connect_in(ncp);
+ break;
+ default:
+ return EPROTONOSUPPORT;
+ }
+ return error;
+}
/*
* Connection expected to be locked
@@ -390,7 +393,6 @@ ncp_sock_disconnect(struct ncp_conn *conn) {
return 0;
}
-#ifdef IPX
static void
ncp_watchdog(struct ncp_conn *conn) {
char *buf;
@@ -422,7 +424,6 @@ ncp_watchdog(struct ncp_conn *conn) {
if (sa) FREE(sa, M_SONAME);
return;
}
-#endif /* IPX */
void
ncp_check_conn(struct ncp_conn *conn) {
@@ -433,7 +434,6 @@ ncp_check_conn(struct ncp_conn *conn) {
s = splnet();
ncp_check_rq(conn);
splx(s);
-#ifdef IPX
- ncp_watchdog(conn);
-#endif
+ if (conn->li.saddr.sa_family == AF_IPX)
+ ncp_watchdog(conn);
}
diff --git a/sys/netncp/ncp_sock.h b/sys/netncp/ncp_sock.h
index acd2380..5172138 100644
--- a/sys/netncp/ncp_sock.h
+++ b/sys/netncp/ncp_sock.h
@@ -41,8 +41,7 @@ struct proc;
struct socket;
struct timeval;
-int ncp_sock_connect_ipx(struct ncp_conn *);
-int ncp_sock_connect_in(struct ncp_conn *);
+int ncp_sock_connect(struct ncp_conn *ncp);
int ncp_sock_recv(struct socket *so, struct mbuf **mp, int *rlen);
int ncp_sock_send(struct socket *so, struct mbuf *data, struct ncp_rq *rqp);
int ncp_sock_disconnect(struct ncp_conn *conn);
diff --git a/sys/netncp/ncp_subr.c b/sys/netncp/ncp_subr.c
index 00c8503..4d208f9 100644
--- a/sys/netncp/ncp_subr.c
+++ b/sys/netncp/ncp_subr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, Boris Popov
+ * Copyright (c) 1999, 2000, 2001 Boris Popov
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,10 +36,9 @@
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/sysctl.h>
#include <sys/malloc.h>
#include <sys/time.h>
-#include <sys/uio.h>
-#include <sys/mbuf.h>
#include <netncp/ncp.h>
#include <netncp/ncp_conn.h>
@@ -76,7 +75,8 @@ ncp_str_dup(char *s) {
void
-ncp_at_exit(struct proc *p) {
+ncp_at_exit(struct proc *p)
+{
struct ncp_conn *ncp, *nncp;
if (ncp_conn_putprochandles(p) == 0) return;
@@ -84,10 +84,9 @@ ncp_at_exit(struct proc *p) {
ncp_conn_locklist(LK_EXCLUSIVE, p);
for (ncp = SLIST_FIRST(&conn_list); ncp; ncp = nncp) {
nncp = SLIST_NEXT(ncp, nc_next);
- if (ncp->ref_cnt != 0) continue;
if (ncp_conn_lock(ncp, p, p->p_ucred,NCPM_READ|NCPM_EXECUTE|NCPM_WRITE))
continue;
- if (ncp_disconnect(ncp) != 0)
+ if (ncp_conn_free(ncp) != 0)
ncp_conn_unlock(ncp,p);
}
ncp_conn_unlocklist(p);
@@ -95,7 +94,26 @@ ncp_at_exit(struct proc *p) {
}
int
-ncp_init(void) {
+ncp_sysctlbyname(char *name, void *old, size_t *oldlenp,
+ void *new, size_t newlen, size_t *retval)
+{
+ int oid[CTL_MAXNAME];
+ int nmlen, plen, error;
+
+ oid[0] = 0; /* sysctl internal magic */
+ oid[1] = 3; /* name2oid */
+ nmlen = sizeof(oid);
+ error = kernel_sysctl(curproc, oid, 2, oid, &nmlen, name, strlen(name), &plen);
+ if (error)
+ return error;
+ error = kernel_sysctl(curproc, oid, plen / sizeof(int), old, oldlenp,
+ new, newlen, retval);
+ return error;
+}
+
+int
+ncp_init(void)
+{
ncp_conn_init();
if (at_exit(ncp_at_exit)) {
NCPFATAL("can't register at_exit handler\n");
@@ -105,32 +123,24 @@ ncp_init(void) {
return 0;
}
-void
-ncp_done(void) {
- struct ncp_conn *ncp, *nncp;
- struct proc *p = curproc;
-
+int
+ncp_done(void)
+{
+ int error;
+
+ error = ncp_conn_destroy();
+ if (error)
+ return error;
untimeout(ncp_timer,NULL,ncp_timer_handle);
rm_at_exit(ncp_at_exit);
- ncp_conn_locklist(LK_EXCLUSIVE, p);
- for (ncp = SLIST_FIRST(&conn_list); ncp; ncp = nncp) {
- nncp = SLIST_NEXT(ncp, nc_next);
- ncp->ref_cnt = 0;
- if (ncp_conn_lock(ncp, p, p->p_ucred,NCPM_READ|NCPM_EXECUTE|NCPM_WRITE)) {
- NCPFATAL("Can't lock connection !\n");
- continue;
- }
- if (ncp_disconnect(ncp) != 0)
- ncp_conn_unlock(ncp,p);
- }
- ncp_conn_unlocklist(p);
- ncp_conn_destroy();
+ return 0;
}
/* tick every second and check for watch dog packets and lost connections */
static void
-ncp_timer(void *arg){
+ncp_timer(void *arg)
+{
struct ncp_conn *conn;
if(ncp_conn_locklist(LK_SHARED | LK_NOWAIT, NULL) == 0) {
@@ -140,116 +150,3 @@ ncp_timer(void *arg){
}
ncp_timer_handle = timeout(ncp_timer,NULL,NCP_TIMER_TICK);
}
-
-int
-ncp_get_bindery_object_id(struct ncp_conn *conn,
- u_int16_t object_type, char *object_name,
- struct ncp_bindery_object *target,
- struct proc *p,struct ucred *cred)
-{
- int error;
- DECLARE_RQ;
-
- NCP_RQ_HEAD_S(23,53,p,cred);
- ncp_rq_word_hl(rqp, object_type);
- ncp_rq_pstring(rqp, object_name);
- checkbad(ncp_request(conn,rqp));
- if (rqp->rpsize < 54) {
- printf("ncp_rp_size %d < 54\n", rqp->rpsize);
- error = EINVAL;
- goto bad;
- }
- target->object_id = ncp_rp_dword_hl(rqp);
- target->object_type = ncp_rp_word_hl(rqp);
- ncp_rp_mem(rqp,(caddr_t)target->object_name, 48);
- NCP_RQ_EXIT;
- return error;
-}
-
-int
-ncp_read(struct ncp_conn *conn, ncp_fh *file, struct uio *uiop, struct ucred *cred) {
- int error = 0, len = 0, retlen=0, tsiz, burstio;
- DECLARE_RQ;
-
- tsiz = uiop->uio_resid;
-#ifdef NCPBURST
- burstio = (ncp_burst_enabled && tsiz > conn->buffer_size);
-#else
- burstio = 0;
-#endif
-
- while (tsiz > 0) {
- if (!burstio) {
- len = min(4096 - (uiop->uio_offset % 4096), tsiz);
- len = min(len, conn->buffer_size);
- NCP_RQ_HEAD(72,uiop->uio_procp,cred);
- ncp_rq_byte(rqp, 0);
- ncp_rq_mem(rqp, (caddr_t)file, 6);
- ncp_rq_dword(rqp, htonl(uiop->uio_offset));
- ncp_rq_word(rqp, htons(len));
- checkbad(ncp_request(conn,rqp));
- retlen = ncp_rp_word_hl(rqp);
- if (uiop->uio_offset & 1)
- ncp_rp_byte(rqp);
- error = nwfs_mbuftouio(&rqp->mrp,uiop,retlen,&rqp->bpos);
- NCP_RQ_EXIT;
- } else {
-#ifdef NCPBURST
- error = ncp_burst_read(conn, file, tsiz, &len, &retlen, uiop, cred);
-#endif
- }
- if (error) break;
- tsiz -= retlen;
- if (retlen < len)
- break;
- }
- return (error);
-}
-
-int
-ncp_write(struct ncp_conn *conn, ncp_fh *file, struct uio *uiop, struct ucred *cred)
-{
- int error = 0, len, tsiz, backup;
- DECLARE_RQ;
-
- if (uiop->uio_iovcnt != 1) {
- printf("%s: can't handle iovcnt>1 !!!\n", __FUNCTION__);
- return EIO;
- }
- tsiz = uiop->uio_resid;
- while (tsiz > 0) {
- len = min(4096 - (uiop->uio_offset % 4096), tsiz);
- len = min(len, conn->buffer_size);
- if (len == 0) {
- printf("gotcha!\n");
- }
- /* rq head */
- NCP_RQ_HEAD(73,uiop->uio_procp,cred);
- ncp_rq_byte(rqp, 0);
- ncp_rq_mem(rqp, (caddr_t)file, 6);
- ncp_rq_dword(rqp, htonl(uiop->uio_offset));
- ncp_rq_word_hl(rqp, len);
- nwfs_uiotombuf(uiop,&rqp->mrq,len,&rqp->bpos);
- checkbad(ncp_request(conn,rqp));
- if (len == 0)
- break;
- NCP_RQ_EXIT;
- if (error) {
- backup = len;
- uiop->uio_iov->iov_base -= backup;
- uiop->uio_iov->iov_len += backup;
- uiop->uio_offset -= backup;
- uiop->uio_resid += backup;
- break;
- }
- tsiz -= len;
- }
- if (error)
- uiop->uio_resid = tsiz;
- switch (error) {
- case NWE_INSUFFICIENT_SPACE:
- error = ENOSPC;
- break;
- }
- return (error);
-}
diff --git a/sys/netncp/ncp_subr.h b/sys/netncp/ncp_subr.h
index 7f493af..4eb6342 100644
--- a/sys/netncp/ncp_subr.h
+++ b/sys/netncp/ncp_subr.h
@@ -45,6 +45,7 @@
#define nwfs_printf NCP_PRINT
/* Maybe this should panic, but I dont like that */
#define NCPFATAL NCP_PRINT
+#define NCPERROR NCP_PRINT
/* socket debugging */
#ifdef NCP_SOCKET_DEBUG
@@ -109,25 +110,15 @@ struct proc;
struct ucred;
int ncp_init(void);
-void ncp_done(void);
+int ncp_done(void);
int ncp_chkintr(struct ncp_conn *conn, struct proc *p);
char*ncp_str_dup(char *s);
+int ncp_sysctlbyname(char *name, void *old, size_t *oldlenp,
+ void *new, size_t newlen, size_t *retval);
/* ncp_crypt.c */
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 ncp_sign(const u_int32_t *state, const char *x, u_int32_t *ostate);
-/* ncp calls */
-int ncp_get_bindery_object_id(struct ncp_conn *conn,
- u_int16_t object_type, char *object_name,
- struct ncp_bindery_object *target,
- struct proc *p,struct ucred *cred);
-int ncp_login_object(struct ncp_conn *conn, unsigned char *username,
- int login_type, unsigned char *password,
- struct proc *p,struct ucred *cred);
-int ncp_read(struct ncp_conn *conn, ncp_fh *file, struct uio *uiop, struct ucred *cred);
-int ncp_write(struct ncp_conn *conn, ncp_fh *file, struct uio *uiop, struct ucred *cred);
-
-
#endif /* _NCP_SUBR_H_ */
OpenPOWER on IntegriCloud