aboutsummaryrefslogtreecommitdiff
path: root/sys/netncp/ncp_ncp.c
diff options
context:
space:
mode:
authorBoris Popov <bp@FreeBSD.org>2001-03-10 05:24:45 +0000
committerBoris Popov <bp@FreeBSD.org>2001-03-10 05:24:45 +0000
commit29ad26f932b432ca14c4ae27243aced04861d089 (patch)
treec6d3d45be821a1f3706fc1c7e88cdf7b2deaee0b /sys/netncp/ncp_ncp.c
parentdf54111fe4f2e0755b863d11a4da201e9f1ff506 (diff)
downloadsrc-29ad26f932b432ca14c4ae27243aced04861d089.tar.gz
src-29ad26f932b432ca14c4ae27243aced04861d089.zip
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.
Notes
Notes: svn path=/head/; revision=74060
Diffstat (limited to 'sys/netncp/ncp_ncp.c')
-rw-r--r--sys/netncp/ncp_ncp.c623
1 files changed, 202 insertions, 421 deletions
diff --git a/sys/netncp/ncp_ncp.c b/sys/netncp/ncp_ncp.c
index 69a77760a752..43a388be81fb 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);
}