More stack for tcpd.
Safecopies renders the NWIOQUERYPARAM ioctl useless. This functionality is now replaced with /dev/ipstat. Write the request to the device and read the answer in one read request.
This commit is contained in:
parent
2d79ae7831
commit
04b478f177
13 changed files with 382 additions and 206 deletions
|
@ -774,7 +774,7 @@ tar: tar.c
|
||||||
|
|
||||||
tcpd: tcpd.c
|
tcpd: tcpd.c
|
||||||
$(CCLD) -o $@ -DPARANOID=0 tcpd.c
|
$(CCLD) -o $@ -DPARANOID=0 tcpd.c
|
||||||
@install -S 4kw $@
|
@install -S 8kw $@
|
||||||
|
|
||||||
tcpdp: tcpd.c
|
tcpdp: tcpd.c
|
||||||
$(CCLD) -o $@ -DPARANOID=1 tcpd.c
|
$(CCLD) -o $@ -DPARANOID=1 tcpd.c
|
||||||
|
|
|
@ -41,10 +41,10 @@ void usage(void);
|
||||||
|
|
||||||
int main(int argc, char*argv[])
|
int main(int argc, char*argv[])
|
||||||
{
|
{
|
||||||
char *tcp_device;
|
char *ipstat_device;
|
||||||
int fd, i;
|
int fd, i, r;
|
||||||
struct svrqueryparam qpar;
|
char *query, *pval;
|
||||||
char *pval;
|
size_t len;
|
||||||
struct timeval uptime;
|
struct timeval uptime;
|
||||||
clock_t now;
|
clock_t now;
|
||||||
int fl;
|
int fl;
|
||||||
|
@ -80,22 +80,29 @@ int main(int argc, char*argv[])
|
||||||
numerical= !!n_flag;
|
numerical= !!n_flag;
|
||||||
verbose= !!v_flag;
|
verbose= !!v_flag;
|
||||||
|
|
||||||
tcp_device= TCP_DEVICE;
|
ipstat_device= IPSTAT_DEVICE;
|
||||||
if ((fd= open(tcp_device, O_RDWR)) == -1)
|
if ((fd= open(ipstat_device, O_RDWR)) == -1)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s: unable to open '%s': %s\n", prog_name,
|
fprintf(stderr, "%s: unable to open '%s': %s\n", prog_name,
|
||||||
tcp_device, strerror(errno));
|
ipstat_device, strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
qpar.param = "tcp_conn_table";
|
query= "tcp_conn_table";
|
||||||
qpar.psize = strlen(qpar.param);
|
len= strlen(query);
|
||||||
qpar.value = values;
|
r= write(fd, query, len);
|
||||||
qpar.vsize = sizeof(values);
|
if (r != len)
|
||||||
if (ioctl(fd, NWIOQUERYPARAM, &qpar) == -1)
|
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s: queryparam failed: %s\n", prog_name,
|
fprintf(stderr, "%s: write to %s failed: %s\n",
|
||||||
strerror(errno));
|
prog_name, ipstat_device, r < 0 ? strerror(errno) :
|
||||||
|
"short write");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
r= read(fd, values, sizeof(values));
|
||||||
|
if (r == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: read from %s failed: %s\n", prog_name,
|
||||||
|
ipstat_device, strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
pval= values;
|
pval= values;
|
||||||
|
|
|
@ -48,10 +48,10 @@ void usage(void);
|
||||||
|
|
||||||
int main(int argc, char*argv[])
|
int main(int argc, char*argv[])
|
||||||
{
|
{
|
||||||
char *udp_device;
|
char *ipstat_device;
|
||||||
int fd, i;
|
int fd, i, r;
|
||||||
struct svrqueryparam qpar;
|
size_t psize;
|
||||||
char *pval;
|
char *pval, *param;
|
||||||
struct timeval uptime;
|
struct timeval uptime;
|
||||||
clock_t now;
|
clock_t now;
|
||||||
int fl;
|
int fl;
|
||||||
|
@ -82,11 +82,11 @@ int main(int argc, char*argv[])
|
||||||
inclSel= !!a_flag;
|
inclSel= !!a_flag;
|
||||||
numerical= !!n_flag;
|
numerical= !!n_flag;
|
||||||
|
|
||||||
udp_device= UDP_DEVICE;
|
ipstat_device= IPSTAT_DEVICE;
|
||||||
if ((fd= open(udp_device, O_RDWR)) == -1)
|
if ((fd= open(ipstat_device, O_RDWR)) == -1)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s: unable to open '%s': %s\n", prog_name,
|
fprintf(stderr, "%s: unable to open '%s': %s\n", prog_name,
|
||||||
udp_device, strerror(errno));
|
ipstat_device, strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,14 +99,21 @@ int main(int argc, char*argv[])
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
qpar.param = "udp_fd_table";
|
param= "udp_fd_table";
|
||||||
qpar.psize = strlen(qpar.param);
|
psize= strlen(param);
|
||||||
qpar.value = valuesl;
|
r= write(fd, param, psize);
|
||||||
qpar.vsize = v_size;
|
if (r != psize)
|
||||||
if (ioctl(fd, NWIOQUERYPARAM, &qpar) == -1)
|
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s: queryparam failed: %s\n", prog_name,
|
fprintf(stderr, "%s: write to %s failed: %s\n", prog_name,
|
||||||
strerror(errno));
|
ipstat_device,
|
||||||
|
r < 0 ? strerror(errno) : "short write");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
r= read(fd, valuesl, v_size);
|
||||||
|
if (r < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: read from %s failed: %s\n", prog_name,
|
||||||
|
ipstat_device, strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
pval= valuesl;
|
pval= valuesl;
|
||||||
|
@ -120,14 +127,21 @@ int main(int argc, char*argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get address, size, and element size of the UDP port table */
|
/* Get address, size, and element size of the UDP port table */
|
||||||
qpar.param = "&udp_port_table,$udp_port_table,$udp_port_table[0]";
|
param = "&udp_port_table,$udp_port_table,$udp_port_table[0]";
|
||||||
qpar.psize = strlen(qpar.param);
|
psize = strlen(param);
|
||||||
qpar.value = values;
|
r= write(fd, param, psize);
|
||||||
qpar.vsize = sizeof(values);
|
if (r != psize)
|
||||||
if (ioctl(fd, NWIOQUERYPARAM, &qpar) == -1)
|
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s: queryparam failed: %s\n", prog_name,
|
fprintf(stderr, "%s: write to %s failed: %s\n", prog_name,
|
||||||
strerror(errno));
|
ipstat_device,
|
||||||
|
r < 0 ? strerror(errno) : "short write");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
r= read(fd, values, sizeof(values));
|
||||||
|
if (r < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: read from %s failed: %s\n", prog_name,
|
||||||
|
ipstat_device, strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
pval= values;
|
pval= values;
|
||||||
|
@ -170,14 +184,21 @@ int main(int argc, char*argv[])
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
qpar.param = "udp_port_table";
|
param = "udp_port_table";
|
||||||
qpar.psize = strlen(qpar.param);
|
psize = strlen(param);
|
||||||
qpar.value = valuesl;
|
r= write(fd, param, psize);
|
||||||
qpar.vsize = v_size;
|
if (r != psize)
|
||||||
if (ioctl(fd, NWIOQUERYPARAM, &qpar) == -1)
|
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s: queryparam failed: %s\n", prog_name,
|
fprintf(stderr, "%s: write to %s failed: %s\n", prog_name,
|
||||||
strerror(errno));
|
ipstat_device,
|
||||||
|
r < 0 ? strerror(errno) : "short write");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
r= read(fd, valuesl, v_size);
|
||||||
|
if (r < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: read from %s failed: %s\n", prog_name,
|
||||||
|
ipstat_device, strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
pval= valuesl;
|
pval= valuesl;
|
||||||
|
|
|
@ -53,8 +53,6 @@
|
||||||
#define NWIOSPSIPOPT _IOW('n', 80, struct nwio_psipopt)
|
#define NWIOSPSIPOPT _IOW('n', 80, struct nwio_psipopt)
|
||||||
#define NWIOGPSIPOPT _IOR('n', 81, struct nwio_psipopt)
|
#define NWIOGPSIPOPT _IOR('n', 81, struct nwio_psipopt)
|
||||||
|
|
||||||
#define NWIOQUERYPARAM _IORW('n',96, struct svrqueryparam)
|
|
||||||
|
|
||||||
#endif /* _NET__IOCTL_H */
|
#endif /* _NET__IOCTL_H */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -14,6 +14,7 @@ _PROTOTYPE (int iruserok, (unsigned long raddr, int superuser,
|
||||||
_PROTOTYPE (int rcmd, (char **ahost, int rport, const char *locuser,
|
_PROTOTYPE (int rcmd, (char **ahost, int rport, const char *locuser,
|
||||||
const char *remuser, const char *cmd, int *fd2p) );
|
const char *remuser, const char *cmd, int *fd2p) );
|
||||||
|
|
||||||
|
#define IPSTAT_DEVICE "/dev/ipstat"
|
||||||
#define ETH_DEVICE "/dev/eth"
|
#define ETH_DEVICE "/dev/eth"
|
||||||
#define IP_DEVICE "/dev/ip"
|
#define IP_DEVICE "/dev/ip"
|
||||||
#define TCP_DEVICE "/dev/tcp"
|
#define TCP_DEVICE "/dev/tcp"
|
||||||
|
|
|
@ -5,7 +5,7 @@ g = generic
|
||||||
|
|
||||||
# Programs, flags, and libraries
|
# Programs, flags, and libraries
|
||||||
CC = cc
|
CC = cc
|
||||||
CPPFLAGS = -I. -D_MINIX
|
CPPFLAGS = -I. -D_MINIX -DBUF_TRACK_ALLOC_FREE -DBUF_CONSISTENCY_CHECK
|
||||||
CFLAGS = $(OPT) $(CPPFLAGS)
|
CFLAGS = $(OPT) $(CPPFLAGS)
|
||||||
LDFLAGS =
|
LDFLAGS =
|
||||||
LIBS = -lsysutil -lsys
|
LIBS = -lsysutil -lsys
|
||||||
|
|
|
@ -32,7 +32,7 @@ THIS_FILE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ACC_NR ((BUF512_NR+BUF2K_NR+BUF32K_NR)*3)
|
#define ACC_NR ((BUF512_NR+BUF2K_NR+BUF32K_NR)*3)
|
||||||
#define CLIENT_NR 7
|
#define CLIENT_NR 10
|
||||||
|
|
||||||
#define DECLARE_TYPE(Tag, Type, Size) \
|
#define DECLARE_TYPE(Tag, Type, Size) \
|
||||||
typedef struct Tag \
|
typedef struct Tag \
|
||||||
|
|
|
@ -282,10 +282,10 @@ PRIVATE void nw_conf()
|
||||||
PRIVATE void nw_init()
|
PRIVATE void nw_init()
|
||||||
{
|
{
|
||||||
mq_init();
|
mq_init();
|
||||||
qp_init();
|
|
||||||
bf_init();
|
bf_init();
|
||||||
clck_init();
|
clck_init();
|
||||||
sr_init();
|
sr_init();
|
||||||
|
qp_init();
|
||||||
eth_init();
|
eth_init();
|
||||||
arp_init();
|
arp_init();
|
||||||
psip_init();
|
psip_init();
|
||||||
|
|
|
@ -139,6 +139,7 @@ static void check_dev(int type, int ifno)
|
||||||
if (ifno == ifdefault) check_ln(device, dvp->defname);
|
if (ifno == ifdefault) check_ln(device, dvp->defname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
check_mknod(IPSTAT_DEV, IPSTAT_MODE, IPSTAT_MINOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cfg_fd;
|
static int cfg_fd;
|
||||||
|
|
|
@ -60,7 +60,11 @@ struct udp_conf
|
||||||
#define NETTYPE_PSIP 2
|
#define NETTYPE_PSIP 2
|
||||||
|
|
||||||
/* To compute the minor device number for a device on an interface. */
|
/* To compute the minor device number for a device on an interface. */
|
||||||
#define if2minor(ifno, dev) ((ifno) * 8 + (dev))
|
#define if2minor(ifno, dev) (1 + (ifno) * 8 + (dev))
|
||||||
|
|
||||||
|
#define IPSTAT_DEV "/dev/ipstat"
|
||||||
|
#define IPSTAT_MODE 0666 /* Is this right? What about just setuid apps */
|
||||||
|
#define IPSTAT_MINOR 0 /* Minor number of /dev/ipstat */
|
||||||
|
|
||||||
/* Offsets of the minor device numbers within a group per interface. */
|
/* Offsets of the minor device numbers within a group per interface. */
|
||||||
#define ETH_DEV_OFF 0
|
#define ETH_DEV_OFF 0
|
||||||
|
|
|
@ -7,6 +7,7 @@ Created: June 1995 by Philip Homburg <philip@f-mnx.phicoh.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "inet.h"
|
#include "inet.h"
|
||||||
|
#include "generic/assert.h"
|
||||||
|
|
||||||
#include <sys/svrctl.h>
|
#include <sys/svrctl.h>
|
||||||
#ifdef __minix_vmd
|
#ifdef __minix_vmd
|
||||||
|
@ -27,14 +28,25 @@ Created: June 1995 by Philip Homburg <philip@f-mnx.phicoh.com>
|
||||||
#include "qp.h"
|
#include "qp.h"
|
||||||
#include "sr_int.h"
|
#include "sr_int.h"
|
||||||
|
|
||||||
FORWARD int get_userdata ARGS(( int proc, vir_bytes vaddr, vir_bytes vlen,
|
THIS_FILE
|
||||||
void *buffer ));
|
|
||||||
FORWARD int get_userdata_s ARGS(( int proc, int gid, vir_bytes vlen,
|
#define MAX_REQ 1024 /* Maximum size of a request */
|
||||||
void *buffer ));
|
|
||||||
FORWARD int put_userdata ARGS(( int proc, vir_bytes vaddr, vir_bytes vlen,
|
#define QP_FD_NR 4
|
||||||
void *buffer ));
|
|
||||||
FORWARD int iqp_getc ARGS(( void ));
|
typedef struct qp_fd
|
||||||
FORWARD void iqp_putc ARGS(( int c ));
|
{
|
||||||
|
int qf_flags;
|
||||||
|
int qf_srfd;
|
||||||
|
get_userdata_t qf_get_userdata;
|
||||||
|
put_userdata_t qf_put_userdata;
|
||||||
|
acc_t *qf_req_pkt;
|
||||||
|
} qp_fd_t;
|
||||||
|
|
||||||
|
#define QFF_EMPTY 0
|
||||||
|
#define QFF_INUSE 1
|
||||||
|
|
||||||
|
PRIVATE qp_fd_t qp_fd_table[QP_FD_NR];
|
||||||
|
|
||||||
PRIVATE struct export_param_list inet_ex_list[]=
|
PRIVATE struct export_param_list inet_ex_list[]=
|
||||||
{
|
{
|
||||||
|
@ -51,24 +63,207 @@ PRIVATE struct export_param_list inet_ex_list[]=
|
||||||
PRIVATE struct export_params inet_ex_params= { inet_ex_list, NULL };
|
PRIVATE struct export_params inet_ex_params= { inet_ex_list, NULL };
|
||||||
|
|
||||||
PRIVATE struct queryvars {
|
PRIVATE struct queryvars {
|
||||||
int proc;
|
/* Input */
|
||||||
struct svrqueryparam qpar;
|
acc_t *param;
|
||||||
char parbuf[256], valbuf[256];
|
|
||||||
char *param, *value;
|
/* Output */
|
||||||
int r;
|
qp_fd_t *qp_fd;
|
||||||
|
off_t fd_offset;
|
||||||
|
size_t rd_bytes_left;
|
||||||
|
off_t outbuf_off;
|
||||||
|
char outbuf[256];
|
||||||
|
|
||||||
|
int r; /* result */
|
||||||
} *qvars;
|
} *qvars;
|
||||||
|
|
||||||
|
|
||||||
|
FORWARD int qp_open ARGS(( int port, int srfd,
|
||||||
|
get_userdata_t get_userdata, put_userdata_t put_userdata,
|
||||||
|
put_pkt_t put_pkt, select_res_t select_res ));
|
||||||
|
FORWARD void qp_close ARGS(( int fd ));
|
||||||
|
FORWARD int qp_read ARGS(( int fd, size_t count ));
|
||||||
|
FORWARD int qp_write ARGS(( int fd, size_t count ));
|
||||||
|
FORWARD int qp_ioctl ARGS(( int fd, ioreq_t req ));
|
||||||
|
FORWARD int qp_cancel ARGS(( int fd, int which_operation ));
|
||||||
|
FORWARD int qp_select ARGS(( int fd, unsigned operations ));
|
||||||
|
FORWARD qp_fd_t *get_qp_fd ARGS(( int fd ));
|
||||||
|
FORWARD int do_query ARGS(( qp_fd_t *qp_fd, acc_t *pkt, int count ));
|
||||||
|
FORWARD int qp_getc ARGS(( void ));
|
||||||
|
FORWARD void qp_putc ARGS(( struct queryvars *qv, int c ));
|
||||||
|
FORWARD void qp_buffree ARGS(( int priority ));
|
||||||
|
#ifdef BUF_CONSISTENCY_CHECK
|
||||||
|
FORWARD void qp_bufcheck ARGS(( void ));
|
||||||
|
#endif
|
||||||
|
|
||||||
PUBLIC void qp_init()
|
PUBLIC void qp_init()
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
qp_export(&inet_ex_params);
|
qp_export(&inet_ex_params);
|
||||||
|
|
||||||
|
for (i= 0; i<QP_FD_NR; i++)
|
||||||
|
qp_fd_table[i].qf_flags= QFF_EMPTY;
|
||||||
|
|
||||||
|
#ifndef BUF_CONSISTENCY_CHECK
|
||||||
|
bf_logon(qp_buffree);
|
||||||
|
#else
|
||||||
|
bf_logon(qp_buffree, qp_bufcheck);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sr_add_minor(IPSTAT_MINOR, 0, qp_open, qp_close, qp_read, qp_write,
|
||||||
|
qp_ioctl, qp_cancel, qp_select);
|
||||||
}
|
}
|
||||||
|
|
||||||
PUBLIC int qp_query(proc, argp)
|
PRIVATE int qp_open(port, srfd, get_userdata, put_userdata, put_pkt,
|
||||||
int proc;
|
select_res)
|
||||||
vir_bytes argp;
|
int port;
|
||||||
|
int srfd;
|
||||||
|
get_userdata_t get_userdata;
|
||||||
|
put_userdata_t put_userdata;
|
||||||
|
put_pkt_t put_pkt;
|
||||||
|
select_res_t select_res;
|
||||||
{
|
{
|
||||||
/* Return values, sizes, or addresses of variables in MM space. */
|
int i;
|
||||||
|
qp_fd_t *qp_fd;
|
||||||
|
|
||||||
|
for (i= 0; i< QP_FD_NR; i++)
|
||||||
|
{
|
||||||
|
if (!(qp_fd_table[i].qf_flags & QFF_INUSE))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i >= QP_FD_NR)
|
||||||
|
return EAGAIN;
|
||||||
|
qp_fd= &qp_fd_table[i];
|
||||||
|
qp_fd->qf_flags= QFF_INUSE;
|
||||||
|
qp_fd->qf_srfd= srfd;
|
||||||
|
qp_fd->qf_get_userdata= get_userdata;
|
||||||
|
qp_fd->qf_put_userdata= put_userdata;
|
||||||
|
qp_fd->qf_req_pkt= NULL;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRIVATE void qp_close(fd)
|
||||||
|
int fd;
|
||||||
|
{
|
||||||
|
qp_fd_t *qp_fd;
|
||||||
|
|
||||||
|
qp_fd= get_qp_fd(fd);
|
||||||
|
qp_fd->qf_flags= QFF_EMPTY;
|
||||||
|
if (qp_fd->qf_req_pkt)
|
||||||
|
{
|
||||||
|
bf_afree(qp_fd->qf_req_pkt);
|
||||||
|
qp_fd->qf_req_pkt= NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PRIVATE int qp_read(fd, count)
|
||||||
|
int fd;
|
||||||
|
size_t count;
|
||||||
|
{
|
||||||
|
int r, err;
|
||||||
|
size_t len;
|
||||||
|
acc_t *pkt;
|
||||||
|
qp_fd_t *qp_fd;
|
||||||
|
|
||||||
|
qp_fd= get_qp_fd(fd);
|
||||||
|
pkt= qp_fd->qf_req_pkt;
|
||||||
|
qp_fd->qf_req_pkt= NULL;
|
||||||
|
if (!pkt)
|
||||||
|
{
|
||||||
|
/* Nothing to do */
|
||||||
|
qp_fd->qf_put_userdata(qp_fd->qf_srfd, EIO, 0,
|
||||||
|
FALSE /* !for_ioctl*/);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
r= do_query(qp_fd, pkt, count);
|
||||||
|
qp_fd->qf_put_userdata(qp_fd->qf_srfd, r, 0,
|
||||||
|
FALSE /* !for_ioctl*/);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRIVATE int qp_write(fd, count)
|
||||||
|
int fd;
|
||||||
|
size_t count;
|
||||||
|
{
|
||||||
|
acc_t *pkt;
|
||||||
|
qp_fd_t *qp_fd;
|
||||||
|
|
||||||
|
qp_fd= get_qp_fd(fd);
|
||||||
|
if (count > MAX_REQ)
|
||||||
|
{
|
||||||
|
qp_fd->qf_get_userdata(qp_fd->qf_srfd, ENOMEM, 0,
|
||||||
|
FALSE /* !for_ioctl*/);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
pkt= qp_fd->qf_get_userdata(qp_fd->qf_srfd, 0, count,
|
||||||
|
FALSE /* !for_ioctl*/);
|
||||||
|
if (!pkt)
|
||||||
|
{
|
||||||
|
qp_fd->qf_get_userdata(qp_fd->qf_srfd, EFAULT, 0,
|
||||||
|
FALSE /* !for_ioctl*/);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
if (qp_fd->qf_req_pkt)
|
||||||
|
{
|
||||||
|
bf_afree(qp_fd->qf_req_pkt);
|
||||||
|
qp_fd->qf_req_pkt= NULL;
|
||||||
|
}
|
||||||
|
qp_fd->qf_req_pkt= pkt;
|
||||||
|
qp_fd->qf_get_userdata(qp_fd->qf_srfd, count, 0,
|
||||||
|
FALSE /* !for_ioctl*/);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRIVATE int qp_ioctl(fd, req)
|
||||||
|
int fd;
|
||||||
|
ioreq_t req;
|
||||||
|
{
|
||||||
|
qp_fd_t *qp_fd;
|
||||||
|
|
||||||
|
qp_fd= get_qp_fd(fd);
|
||||||
|
qp_fd->qf_get_userdata(qp_fd->qf_srfd, ENOTTY, 0,
|
||||||
|
TRUE /* for_ioctl*/);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRIVATE int qp_cancel(fd, which_operation)
|
||||||
|
int fd;
|
||||||
|
int which_operation;
|
||||||
|
{
|
||||||
|
ip_panic(( "qp_cancel: should not be here, no blocking calls" ));
|
||||||
|
}
|
||||||
|
|
||||||
|
PRIVATE int qp_select(fd, operations)
|
||||||
|
int fd;
|
||||||
|
unsigned operations;
|
||||||
|
{
|
||||||
|
unsigned resops;
|
||||||
|
|
||||||
|
resops= 0;
|
||||||
|
if (operations & SR_SELECT_READ)
|
||||||
|
resops |= SR_SELECT_READ;
|
||||||
|
if (operations & SR_SELECT_WRITE)
|
||||||
|
resops |= SR_SELECT_WRITE;
|
||||||
|
return resops;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRIVATE qp_fd_t *get_qp_fd(fd)
|
||||||
|
int fd;
|
||||||
|
{
|
||||||
|
qp_fd_t *qp_fd;
|
||||||
|
|
||||||
|
assert(fd >= 0 && fd < QP_FD_NR);
|
||||||
|
qp_fd= &qp_fd_table[fd];
|
||||||
|
assert(qp_fd->qf_flags & QFF_INUSE);
|
||||||
|
return qp_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRIVATE int do_query(qp_fd, pkt, count)
|
||||||
|
qp_fd_t *qp_fd;
|
||||||
|
acc_t *pkt;
|
||||||
|
int count;
|
||||||
|
{
|
||||||
struct queryvars qv;
|
struct queryvars qv;
|
||||||
void *addr;
|
void *addr;
|
||||||
size_t n, size;
|
size_t n, size;
|
||||||
|
@ -76,143 +271,118 @@ vir_bytes argp;
|
||||||
int more;
|
int more;
|
||||||
static char hex[]= "0123456789ABCDEF";
|
static char hex[]= "0123456789ABCDEF";
|
||||||
|
|
||||||
qv.r= get_userdata(proc, argp, sizeof(qv.qpar), &qv.qpar);
|
|
||||||
|
|
||||||
/* Export these to mq_getc() and mq_putc(). */
|
|
||||||
qvars= &qv;
|
qvars= &qv;
|
||||||
qv.proc= proc;
|
qv.param= pkt; pkt= NULL;
|
||||||
qv.param= qv.parbuf + sizeof(qv.parbuf);
|
qv.qp_fd= qp_fd;
|
||||||
qv.value= qv.valbuf;
|
qv.fd_offset= 0;
|
||||||
|
qv.outbuf_off= 0;
|
||||||
|
qv.rd_bytes_left= count;
|
||||||
|
qv.r= 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
more= queryparam(iqp_getc, &addr, &size);
|
more= queryparam(qp_getc, &addr, &size);
|
||||||
for (n= 0; n < size; n++) {
|
for (n= 0; n < size; n++) {
|
||||||
byte= ((u8_t *) addr)[n];
|
byte= ((u8_t *) addr)[n];
|
||||||
iqp_putc(hex[byte >> 4]);
|
qp_putc(&qv, hex[byte >> 4]);
|
||||||
iqp_putc(hex[byte & 0x0F]);
|
qp_putc(&qv, hex[byte & 0x0F]);
|
||||||
}
|
}
|
||||||
iqp_putc(more ? ',' : 0);
|
qp_putc(&qv, more ? ',' : 0);
|
||||||
|
if (qv.r)
|
||||||
|
break;
|
||||||
} while (more);
|
} while (more);
|
||||||
|
if (qv.param)
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
bf_afree(qv.param);
|
||||||
|
qv.param= NULL;
|
||||||
|
}
|
||||||
|
if (qv.r)
|
||||||
return qv.r;
|
return qv.r;
|
||||||
|
return qv.fd_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUBLIC int qp_query_s(proc, gid)
|
PRIVATE int qp_getc()
|
||||||
int proc;
|
|
||||||
int gid;
|
|
||||||
{
|
|
||||||
/* Return values, sizes, or addresses of variables in MM space. */
|
|
||||||
|
|
||||||
struct queryvars qv;
|
|
||||||
void *addr;
|
|
||||||
size_t n, size;
|
|
||||||
int byte;
|
|
||||||
int more;
|
|
||||||
static char hex[]= "0123456789ABCDEF";
|
|
||||||
|
|
||||||
qv.r= get_userdata_s(proc, gid, sizeof(qv.qpar), &qv.qpar);
|
|
||||||
|
|
||||||
/* Export these to mq_getc() and mq_putc(). */
|
|
||||||
qvars= &qv;
|
|
||||||
qv.proc= proc;
|
|
||||||
qv.param= qv.parbuf + sizeof(qv.parbuf);
|
|
||||||
qv.value= qv.valbuf;
|
|
||||||
|
|
||||||
do {
|
|
||||||
more= queryparam(iqp_getc, &addr, &size);
|
|
||||||
for (n= 0; n < size; n++) {
|
|
||||||
byte= ((u8_t *) addr)[n];
|
|
||||||
iqp_putc(hex[byte >> 4]);
|
|
||||||
iqp_putc(hex[byte & 0x0F]);
|
|
||||||
}
|
|
||||||
iqp_putc(more ? ',' : 0);
|
|
||||||
} while (more);
|
|
||||||
return qv.r;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PRIVATE int iqp_getc()
|
|
||||||
{
|
{
|
||||||
/* Return one character of the names to search for. */
|
/* Return one character of the names to search for. */
|
||||||
|
acc_t *pkt;
|
||||||
struct queryvars *qv= qvars;
|
struct queryvars *qv= qvars;
|
||||||
size_t n;
|
u8_t c;
|
||||||
|
|
||||||
if (qv->r != OK || qv->qpar.psize == 0) return 0;
|
pkt= qv->param;
|
||||||
if (qv->param == qv->parbuf + sizeof(qv->parbuf)) {
|
qv->param= NULL;
|
||||||
/* Need to fill the parameter buffer. */
|
if (pkt == NULL)
|
||||||
n= sizeof(qv->parbuf);
|
return 0;
|
||||||
if (qv->qpar.psize < n) n= qv->qpar.psize;
|
|
||||||
qv->r= get_userdata(qv->proc, (vir_bytes) qv->qpar.param, n,
|
assert(bf_bufsize(pkt) > 0);
|
||||||
qv->parbuf);
|
c= ptr2acc_data(pkt)[0];
|
||||||
if (qv->r != OK) return 0;
|
if (bf_bufsize(pkt) > 1)
|
||||||
qv->qpar.param+= n;
|
qv->param= bf_delhead(pkt, 1);
|
||||||
qv->param= qv->parbuf;
|
else
|
||||||
|
{
|
||||||
|
bf_afree(pkt);
|
||||||
|
qv->param= NULL;
|
||||||
}
|
}
|
||||||
qv->qpar.psize--;
|
|
||||||
return (u8_t) *qv->param++;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PRIVATE void qp_putc(qv, c)
|
||||||
PRIVATE void iqp_putc(c)
|
struct queryvars *qv;
|
||||||
int c;
|
int c;
|
||||||
{
|
{
|
||||||
/* Send one character back to the user. */
|
/* Send one character back to the user. */
|
||||||
struct queryvars *qv= qvars;
|
acc_t *pkt;
|
||||||
size_t n;
|
qp_fd_t *qp_fd;
|
||||||
|
size_t n, bytes_left;
|
||||||
|
off_t off;
|
||||||
|
|
||||||
if (qv->r != OK || qv->qpar.vsize == 0) return;
|
bytes_left= qv->rd_bytes_left;
|
||||||
*qv->value++= c;
|
if (qv->r || bytes_left == 0)
|
||||||
qv->qpar.vsize--;
|
return;
|
||||||
if (qv->value == qv->valbuf + sizeof(qv->valbuf)
|
|
||||||
|| c == 0 || qv->qpar.vsize == 0) {
|
off= qv->outbuf_off;
|
||||||
/* Copy the value buffer to user space. */
|
assert(off < sizeof(qv->outbuf));
|
||||||
n= qv->value - qv->valbuf;
|
qv->outbuf[off]= c;
|
||||||
qv->r= put_userdata(qv->proc, (vir_bytes) qv->qpar.value, n,
|
off++;
|
||||||
qv->valbuf);
|
bytes_left--;
|
||||||
qv->qpar.value+= n;
|
qv->rd_bytes_left= bytes_left;
|
||||||
qv->value= qv->valbuf;
|
if (c != '\0' && off < sizeof(qv->outbuf) && bytes_left != 0)
|
||||||
|
{
|
||||||
|
qv->outbuf_off= off;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pkt= bf_memreq(off);
|
||||||
|
assert(pkt->acc_next == NULL);
|
||||||
|
memcpy(ptr2acc_data(pkt), qv->outbuf, off);
|
||||||
|
qp_fd= qv->qp_fd;
|
||||||
|
qv->r= qp_fd->qf_put_userdata(qp_fd->qf_srfd, qv->fd_offset,
|
||||||
|
pkt, FALSE /* !for_ioctl*/ );
|
||||||
|
qv->fd_offset += off;
|
||||||
|
qv->outbuf_off= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRIVATE void qp_buffree (priority)
|
||||||
|
int priority;
|
||||||
|
{
|
||||||
|
/* For the moment, we are not going to free anything */
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef BUF_CONSISTENCY_CHECK
|
||||||
|
PRIVATE void qp_bufcheck()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
qp_fd_t *qp_fd;
|
||||||
|
|
||||||
|
for (i= 0, qp_fd= qp_fd_table; i<QP_FD_NR; i++, qp_fd++)
|
||||||
|
{
|
||||||
|
if (!(qp_fd->qf_flags & QFF_INUSE))
|
||||||
|
continue;
|
||||||
|
if (qp_fd->qf_req_pkt)
|
||||||
|
bf_check_acc(qp_fd->qf_req_pkt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PRIVATE int get_userdata(proc, vaddr, vlen, buffer)
|
|
||||||
int proc;
|
|
||||||
vir_bytes vaddr;
|
|
||||||
vir_bytes vlen;
|
|
||||||
void *buffer;
|
|
||||||
{
|
|
||||||
#ifdef __minix_vmd
|
|
||||||
return sys_copy(proc, SEG_D, (phys_bytes)vaddr, this_proc, SEG_D,
|
|
||||||
(phys_bytes)buffer, (phys_bytes)vlen);
|
|
||||||
#else /* Minix 3 */
|
|
||||||
return sys_vircopy(proc, D, vaddr, SELF, D, (vir_bytes)buffer, vlen);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PRIVATE int get_userdata_s(proc, gid, vlen, buffer)
|
|
||||||
int proc;
|
|
||||||
int gid;
|
|
||||||
vir_bytes vlen;
|
|
||||||
void *buffer;
|
|
||||||
{
|
|
||||||
return sys_safecopyfrom(proc, gid, 0, (vir_bytes)buffer, vlen, D);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PRIVATE int put_userdata(proc, vaddr, vlen, buffer)
|
|
||||||
int proc;
|
|
||||||
vir_bytes vaddr;
|
|
||||||
vir_bytes vlen;
|
|
||||||
void *buffer;
|
|
||||||
{
|
|
||||||
#ifdef __minix_vmd
|
|
||||||
return sys_copy(this_proc, SEG_D, (phys_bytes)buffer,
|
|
||||||
proc, SEG_D, (phys_bytes)vaddr, (phys_bytes)vlen);
|
|
||||||
#else /* Minix 3 */
|
|
||||||
return sys_vircopy(SELF, D, (vir_bytes)buffer, proc, D, vaddr, vlen);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $PchId: qp.c,v 1.7 2005/06/28 14:25:25 philip Exp $
|
* $PchId: qp.c,v 1.7 2005/06/28 14:25:25 philip Exp $
|
||||||
|
|
|
@ -12,8 +12,6 @@ Copyright 1995 Philip Homburg
|
||||||
#define INET__QP_H
|
#define INET__QP_H
|
||||||
|
|
||||||
void qp_init ARGS(( void ));
|
void qp_init ARGS(( void ));
|
||||||
int qp_query ARGS(( int proc, vir_bytes argp ));
|
|
||||||
int qp_query_s ARGS(( int proc, int gid ));
|
|
||||||
|
|
||||||
#endif /* INET__QP_H */
|
#endif /* INET__QP_H */
|
||||||
|
|
||||||
|
|
|
@ -382,18 +382,6 @@ mq_t *m;
|
||||||
break;
|
break;
|
||||||
case DEV_IOCTL3:
|
case DEV_IOCTL3:
|
||||||
request= m->mq_mess.NDEV_IOCTL;
|
request= m->mq_mess.NDEV_IOCTL;
|
||||||
|
|
||||||
/* There should be a better way to do this... */
|
|
||||||
if (request == NWIOQUERYPARAM)
|
|
||||||
{
|
|
||||||
r= qp_query(m->mq_mess.NDEV_PROC,
|
|
||||||
(vir_bytes)m->mq_mess.NDEV_BUFFER);
|
|
||||||
r= sr_put_userdata(sr_fd-sr_fd_table, r, NULL, 1);
|
|
||||||
assert(r == OK);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* And now, we continue with our regular program. */
|
|
||||||
size= (request >> 16) & _IOCPARM_MASK;
|
size= (request >> 16) & _IOCPARM_MASK;
|
||||||
if (size>MAX_IOCTL_S)
|
if (size>MAX_IOCTL_S)
|
||||||
{
|
{
|
||||||
|
@ -491,18 +479,6 @@ mq_t *m;
|
||||||
break;
|
break;
|
||||||
case DEV_IOCTL_S:
|
case DEV_IOCTL_S:
|
||||||
request= m->mq_mess.NDEV_IOCTL;
|
request= m->mq_mess.NDEV_IOCTL;
|
||||||
|
|
||||||
/* There should be a better way to do this... */
|
|
||||||
if (request == NWIOQUERYPARAM)
|
|
||||||
{
|
|
||||||
r= qp_query_s(m->mq_mess.NDEV_PROC,
|
|
||||||
(vir_bytes)m->mq_mess.NDEV_BUFFER);
|
|
||||||
r= sr_put_userdata(sr_fd-sr_fd_table, r, NULL, 1);
|
|
||||||
assert(r == OK);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* And now, we continue with our regular program. */
|
|
||||||
size= (request >> 16) & _IOCPARM_MASK;
|
size= (request >> 16) & _IOCPARM_MASK;
|
||||||
if (size>MAX_IOCTL_S)
|
if (size>MAX_IOCTL_S)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue