int main(int argc, char*argv[])
{
- char *udp_device;
- int fd, i;
- struct svrqueryparam qpar;
- char *pval;
+ char *ipstat_device;
+ int fd, i, r;
+ size_t psize;
+ char *pval, *param;
struct timeval uptime;
clock_t now;
int fl;
inclSel= !!a_flag;
numerical= !!n_flag;
- udp_device= UDP_DEVICE;
- if ((fd= open(udp_device, O_RDWR)) == -1)
+ ipstat_device= IPSTAT_DEVICE;
+ if ((fd= open(ipstat_device, O_RDWR)) == -1)
{
fprintf(stderr, "%s: unable to open '%s': %s\n", prog_name,
- udp_device, strerror(errno));
+ ipstat_device, strerror(errno));
exit(1);
}
exit(1);
}
- qpar.param = "udp_fd_table";
- qpar.psize = strlen(qpar.param);
- qpar.value = valuesl;
- qpar.vsize = v_size;
- if (ioctl(fd, NWIOQUERYPARAM, &qpar) == -1)
+ param= "udp_fd_table";
+ psize= strlen(param);
+ r= write(fd, param, psize);
+ if (r != psize)
{
- fprintf(stderr, "%s: queryparam failed: %s\n", prog_name,
- strerror(errno));
+ fprintf(stderr, "%s: write to %s failed: %s\n", prog_name,
+ 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);
}
pval= valuesl;
}
/* Get address, size, and element size of the UDP port table */
- qpar.param = "&udp_port_table,$udp_port_table,$udp_port_table[0]";
- qpar.psize = strlen(qpar.param);
- qpar.value = values;
- qpar.vsize = sizeof(values);
- if (ioctl(fd, NWIOQUERYPARAM, &qpar) == -1)
+ param = "&udp_port_table,$udp_port_table,$udp_port_table[0]";
+ psize = strlen(param);
+ r= write(fd, param, psize);
+ if (r != psize)
{
- fprintf(stderr, "%s: queryparam failed: %s\n", prog_name,
- strerror(errno));
+ fprintf(stderr, "%s: write to %s failed: %s\n", prog_name,
+ 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);
}
pval= values;
exit(1);
}
- qpar.param = "udp_port_table";
- qpar.psize = strlen(qpar.param);
- qpar.value = valuesl;
- qpar.vsize = v_size;
- if (ioctl(fd, NWIOQUERYPARAM, &qpar) == -1)
+ param = "udp_port_table";
+ psize = strlen(param);
+ r= write(fd, param, psize);
+ if (r != psize)
{
- fprintf(stderr, "%s: queryparam failed: %s\n", prog_name,
- strerror(errno));
+ fprintf(stderr, "%s: write to %s failed: %s\n", prog_name,
+ 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);
}
pval= valuesl;
*/
#include "inet.h"
+#include "generic/assert.h"
#include <sys/svrctl.h>
#ifdef __minix_vmd
#include "qp.h"
#include "sr_int.h"
-FORWARD int get_userdata ARGS(( int proc, vir_bytes vaddr, vir_bytes vlen,
- void *buffer ));
-FORWARD int get_userdata_s ARGS(( int proc, int gid, vir_bytes vlen,
- void *buffer ));
-FORWARD int put_userdata ARGS(( int proc, vir_bytes vaddr, vir_bytes vlen,
- void *buffer ));
-FORWARD int iqp_getc ARGS(( void ));
-FORWARD void iqp_putc ARGS(( int c ));
+THIS_FILE
+
+#define MAX_REQ 1024 /* Maximum size of a request */
+
+#define QP_FD_NR 4
+
+typedef struct qp_fd
+{
+ 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_params inet_ex_params= { inet_ex_list, NULL };
PRIVATE struct queryvars {
- int proc;
- struct svrqueryparam qpar;
- char parbuf[256], valbuf[256];
- char *param, *value;
- int r;
+ /* Input */
+ acc_t *param;
+
+ /* Output */
+ 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;
+
+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()
{
+ int i;
+
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)
-int proc;
-vir_bytes argp;
+PRIVATE int qp_open(port, srfd, get_userdata, put_userdata, put_pkt,
+ select_res)
+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;
- struct queryvars qv;
- void *addr;
- size_t n, size;
- int byte;
- int more;
- static char hex[]= "0123456789ABCDEF";
+ 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;
+}
- qv.r= get_userdata(proc, argp, sizeof(qv.qpar), &qv.qpar);
+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;
+ }
+}
- /* Export these to mq_getc() and mq_putc(). */
- qvars= &qv;
- qv.proc= proc;
- qv.param= qv.parbuf + sizeof(qv.parbuf);
- qv.value= qv.valbuf;
+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;
+}
- 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 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" ));
}
-PUBLIC int qp_query_s(proc, gid)
-int proc;
-int gid;
+PRIVATE int qp_select(fd, operations)
+int fd;
+unsigned operations;
{
- /* Return values, sizes, or addresses of variables in MM space. */
+ 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;
void *addr;
size_t n, size;
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;
+ qv.param= pkt; pkt= NULL;
+ qv.qp_fd= qp_fd;
+ qv.fd_offset= 0;
+ qv.outbuf_off= 0;
+ qv.rd_bytes_left= count;
+ qv.r= 0;
do {
- more= queryparam(iqp_getc, &addr, &size);
+ more= queryparam(qp_getc, &addr, &size);
for (n= 0; n < size; n++) {
byte= ((u8_t *) addr)[n];
- iqp_putc(hex[byte >> 4]);
- iqp_putc(hex[byte & 0x0F]);
+ qp_putc(&qv, hex[byte >> 4]);
+ qp_putc(&qv, hex[byte & 0x0F]);
}
- iqp_putc(more ? ',' : 0);
+ qp_putc(&qv, more ? ',' : 0);
+ if (qv.r)
+ break;
} while (more);
- return qv.r;
+ if (qv.param)
+ {
+ assert(0);
+ bf_afree(qv.param);
+ qv.param= NULL;
+ }
+ if (qv.r)
+ return qv.r;
+ return qv.fd_offset;
}
-
-PRIVATE int iqp_getc()
+PRIVATE int qp_getc()
{
/* Return one character of the names to search for. */
+ acc_t *pkt;
struct queryvars *qv= qvars;
- size_t n;
-
- if (qv->r != OK || qv->qpar.psize == 0) return 0;
- if (qv->param == qv->parbuf + sizeof(qv->parbuf)) {
- /* Need to fill the parameter buffer. */
- n= sizeof(qv->parbuf);
- if (qv->qpar.psize < n) n= qv->qpar.psize;
- qv->r= get_userdata(qv->proc, (vir_bytes) qv->qpar.param, n,
- qv->parbuf);
- if (qv->r != OK) return 0;
- qv->qpar.param+= n;
- qv->param= qv->parbuf;
+ u8_t c;
+
+ pkt= qv->param;
+ qv->param= NULL;
+ if (pkt == NULL)
+ return 0;
+
+ assert(bf_bufsize(pkt) > 0);
+ c= ptr2acc_data(pkt)[0];
+ if (bf_bufsize(pkt) > 1)
+ qv->param= bf_delhead(pkt, 1);
+ else
+ {
+ bf_afree(pkt);
+ qv->param= NULL;
}
- qv->qpar.psize--;
- return (u8_t) *qv->param++;
-}
+ return c;
+}
-PRIVATE void iqp_putc(c)
+PRIVATE void qp_putc(qv, c)
+struct queryvars *qv;
int c;
{
/* Send one character back to the user. */
- struct queryvars *qv= qvars;
- size_t n;
-
- if (qv->r != OK || qv->qpar.vsize == 0) return;
- *qv->value++= c;
- qv->qpar.vsize--;
- if (qv->value == qv->valbuf + sizeof(qv->valbuf)
- || c == 0 || qv->qpar.vsize == 0) {
- /* Copy the value buffer to user space. */
- n= qv->value - qv->valbuf;
- qv->r= put_userdata(qv->proc, (vir_bytes) qv->qpar.value, n,
- qv->valbuf);
- qv->qpar.value+= n;
- qv->value= qv->valbuf;
+ acc_t *pkt;
+ qp_fd_t *qp_fd;
+ size_t n, bytes_left;
+ off_t off;
+
+ bytes_left= qv->rd_bytes_left;
+ if (qv->r || bytes_left == 0)
+ return;
+
+ off= qv->outbuf_off;
+ assert(off < sizeof(qv->outbuf));
+ qv->outbuf[off]= c;
+ off++;
+ bytes_left--;
+ qv->rd_bytes_left= bytes_left;
+ if (c != '\0' && off < sizeof(qv->outbuf) && bytes_left != 0)
+ {
+ qv->outbuf_off= off;
+ return;
}
-}
-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
+ 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 int get_userdata_s(proc, gid, vlen, buffer)
-int proc;
-int gid;
-vir_bytes vlen;
-void *buffer;
+PRIVATE void qp_buffree (priority)
+int priority;
{
- return sys_safecopyfrom(proc, gid, 0, (vir_bytes)buffer, vlen, D);
+ /* For the moment, we are not going to free anything */
}
-
-PRIVATE int put_userdata(proc, vaddr, vlen, buffer)
-int proc;
-vir_bytes vaddr;
-vir_bytes vlen;
-void *buffer;
+#ifdef BUF_CONSISTENCY_CHECK
+PRIVATE void qp_bufcheck()
{
-#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
+ 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);
+ }
}
-
-
+#endif
/*
* $PchId: qp.c,v 1.7 2005/06/28 14:25:25 philip Exp $