1178784Skmacy/*
2256829Snp * This code lifted from:
3178784Skmacy * 	Simple `echo' pseudo-device KLD
4178784Skmacy * 	Murray Stokely
5178784Skmacy * 	Converted to 5.X by S��ren (Xride) Straarup
6178784Skmacy */
7178784Skmacy
8178784Skmacy/*
9256829Snp * /bin/echo "server,port=9999,addr=192.168.69.142,validate" > /dev/krping
10256829Snp * /bin/echo "client,port=9999,addr=192.168.69.142,validate" > /dev/krping
11178784Skmacy */
12178784Skmacy
13178784Skmacy#include <sys/cdefs.h>
14178784Skmacy__FBSDID("$FreeBSD$");
15178784Skmacy
16178784Skmacy#include <sys/types.h>
17256829Snp#include <sys/module.h>
18178784Skmacy#include <sys/systm.h>  /* uprintf */
19178784Skmacy#include <sys/errno.h>
20178784Skmacy#include <sys/param.h>  /* defines used in kernel.h */
21178784Skmacy#include <sys/kernel.h> /* types used in module initialization */
22178784Skmacy#include <sys/conf.h>   /* cdevsw struct */
23178784Skmacy#include <sys/uio.h>    /* uio struct */
24178784Skmacy#include <sys/malloc.h>
25256829Snp#include <sys/proc.h>
26256829Snp#include <sys/sysctl.h>
27256829Snp#include <machine/stdarg.h>
28178784Skmacy
29178784Skmacy#include "krping.h"
30178784Skmacy
31178784Skmacy#define BUFFERSIZE 512
32178784Skmacy
33256829SnpSYSCTL_NODE(_dev, OID_AUTO, krping, CTLFLAG_RW, 0, "kernel rping module");
34256829Snp
35256829Snpint krping_debug = 0;
36256829SnpSYSCTL_INT(_dev_krping, OID_AUTO, debug, CTLFLAG_RW, &krping_debug, 0 , "");
37256829Snp
38178784Skmacy/* Function prototypes */
39178784Skmacystatic d_open_t      krping_open;
40178784Skmacystatic d_close_t     krping_close;
41178784Skmacystatic d_read_t      krping_read;
42178784Skmacystatic d_write_t     krping_write;
43178784Skmacy
44178784Skmacy/* Character device entry points */
45178784Skmacystatic struct cdevsw krping_cdevsw = {
46178784Skmacy	.d_version = D_VERSION,
47178784Skmacy	.d_open = krping_open,
48178784Skmacy	.d_close = krping_close,
49178784Skmacy	.d_read = krping_read,
50178784Skmacy	.d_write = krping_write,
51178784Skmacy	.d_name = "krping",
52178784Skmacy};
53178784Skmacy
54178784Skmacytypedef struct s_krping {
55178784Skmacy	char msg[BUFFERSIZE];
56178784Skmacy	int len;
57178784Skmacy} krping_t;
58178784Skmacy
59256829Snpstruct stats_list_entry {
60256829Snp	STAILQ_ENTRY(stats_list_entry) link;
61256829Snp	struct krping_stats *stats;
62256829Snp};
63256829SnpSTAILQ_HEAD(stats_list, stats_list_entry);
64256829Snp
65178784Skmacy/* vars */
66178784Skmacystatic struct cdev *krping_dev;
67178784Skmacy
68178784Skmacystatic int
69178784Skmacykrping_loader(struct module *m, int what, void *arg)
70178784Skmacy{
71178784Skmacy	int err = 0;
72178784Skmacy
73178784Skmacy	switch (what) {
74178784Skmacy	case MOD_LOAD:                /* kldload */
75178784Skmacy		krping_init();
76256829Snp		krping_dev = make_dev(&krping_cdevsw, 0, UID_ROOT, GID_WHEEL,
77178784Skmacy					0600, "krping");
78178784Skmacy		printf("Krping device loaded.\n");
79178784Skmacy		break;
80178784Skmacy	case MOD_UNLOAD:
81178784Skmacy		destroy_dev(krping_dev);
82178784Skmacy		printf("Krping device unloaded.\n");
83178784Skmacy		break;
84178784Skmacy	default:
85178784Skmacy		err = EOPNOTSUPP;
86178784Skmacy		break;
87178784Skmacy	}
88256829Snp
89256829Snp	return (err);
90178784Skmacy}
91178784Skmacy
92178784Skmacystatic int
93178784Skmacykrping_open(struct cdev *dev, int oflags, int devtype, struct thread *p)
94178784Skmacy{
95256829Snp
96256829Snp	return (0);
97178784Skmacy}
98178784Skmacy
99178784Skmacystatic int
100178784Skmacykrping_close(struct cdev *dev, int fflag, int devtype, struct thread *p)
101178784Skmacy{
102256829Snp
103178784Skmacy	return 0;
104178784Skmacy}
105178784Skmacy
106256829Snpstatic void
107256829Snpkrping_copy_stats(struct krping_stats *stats, void *arg)
108256829Snp{
109256829Snp	struct stats_list_entry *s;
110256829Snp	struct stats_list *list = arg;
111256829Snp
112256829Snp	s = malloc(sizeof(*s), M_DEVBUF, M_NOWAIT | M_ZERO);
113256829Snp	if (s == NULL)
114256829Snp		return;
115256829Snp	if (stats != NULL) {
116256829Snp		s->stats = malloc(sizeof(*stats), M_DEVBUF, M_NOWAIT | M_ZERO);
117256829Snp		if (s->stats == NULL) {
118256829Snp			free(s, M_DEVBUF);
119256829Snp			return;
120256829Snp		}
121256829Snp		*s->stats = *stats;
122256829Snp	}
123256829Snp	STAILQ_INSERT_TAIL(list, s, link);
124256829Snp}
125256829Snp
126178784Skmacystatic int
127178784Skmacykrping_read(struct cdev *dev, struct uio *uio, int ioflag)
128178784Skmacy{
129256829Snp	int num = 1;
130256829Snp	struct stats_list list;
131256829Snp	struct stats_list_entry *e;
132178784Skmacy
133256829Snp	STAILQ_INIT(&list);
134256829Snp	krping_walk_cb_list(krping_copy_stats, &list);
135256829Snp
136256829Snp	if (STAILQ_EMPTY(&list))
137256829Snp		return (0);
138256829Snp
139178784Skmacy	uprintf("krping: %4s %10s %10s %10s %10s %10s %10s %10s %10s %10s\n",
140256829Snp	    "num", "device", "snd bytes", "snd msgs", "rcv bytes", "rcv msgs",
141256829Snp	    "wr bytes", "wr msgs", "rd bytes", "rd msgs");
142178784Skmacy
143256829Snp	while (!STAILQ_EMPTY(&list)) {
144256829Snp		e = STAILQ_FIRST(&list);
145256829Snp		STAILQ_REMOVE_HEAD(&list, link);
146256829Snp		if (e->stats == NULL)
147256829Snp			uprintf("krping: %d listen\n", num);
148256829Snp		else {
149256829Snp			struct krping_stats *stats = e->stats;
150178784Skmacy
151256829Snp			uprintf("krping: %4d %10s %10llu %10llu %10llu %10llu "
152256829Snp			    "%10llu %10llu %10llu %10llu\n", num, stats->name,
153256829Snp			    stats->send_bytes, stats->send_msgs,
154256829Snp			    stats->recv_bytes, stats->recv_msgs,
155256829Snp			    stats->write_bytes, stats->write_msgs,
156256829Snp			    stats->read_bytes, stats->read_msgs);
157256829Snp			free(stats, M_DEVBUF);
158178784Skmacy		}
159256829Snp		num++;
160256829Snp		free(e, M_DEVBUF);
161178784Skmacy	}
162256829Snp
163256829Snp	return (0);
164178784Skmacy}
165178784Skmacy
166178784Skmacystatic int
167178784Skmacykrping_write(struct cdev *dev, struct uio *uio, int ioflag)
168178784Skmacy{
169178784Skmacy	int err = 0;
170178784Skmacy	int amt;
171178784Skmacy	int remain = BUFFERSIZE;
172178784Skmacy	char *cp;
173178784Skmacy	krping_t *krpingmsg;
174178784Skmacy
175178784Skmacy	krpingmsg = malloc(sizeof *krpingmsg, M_DEVBUF, M_WAITOK|M_ZERO);
176178784Skmacy	if (!krpingmsg) {
177178784Skmacy		uprintf("Could not malloc mem!\n");
178178784Skmacy		return ENOMEM;
179178784Skmacy	}
180178784Skmacy
181178784Skmacy	cp = krpingmsg->msg;
182178784Skmacy	while (uio->uio_resid) {
183178784Skmacy		amt = MIN(uio->uio_resid, remain);
184178784Skmacy		if (amt == 0)
185178784Skmacy			break;
186178784Skmacy
187178784Skmacy		/* Copy the string in from user memory to kernel memory */
188178784Skmacy		err = uiomove(cp, amt, uio);
189178784Skmacy		if (err) {
190178784Skmacy			uprintf("Write failed: bad address!\n");
191178784Skmacy			return err;
192178784Skmacy		}
193178784Skmacy		cp += amt;
194178784Skmacy		remain -= amt;
195178784Skmacy	}
196178784Skmacy
197178784Skmacy	if (uio->uio_resid != 0) {
198178784Skmacy		uprintf("Message too big. max size is %d!\n", BUFFERSIZE);
199178784Skmacy		return EMSGSIZE;
200178784Skmacy	}
201178784Skmacy
202178784Skmacy	/* null terminate and remove the \n */
203178784Skmacy	cp--;
204178784Skmacy	*cp = 0;
205178784Skmacy	krpingmsg->len = (unsigned long)(cp - krpingmsg->msg);
206178784Skmacy	uprintf("krping: write string = |%s|\n", krpingmsg->msg);
207256829Snp	err = krping_doit(krpingmsg->msg, curproc);
208178784Skmacy	free(krpingmsg, M_DEVBUF);
209178784Skmacy	return(err);
210178784Skmacy}
211178784Skmacy
212256829Snpvoid
213256829Snpkrping_printf(void *cookie, const char *fmt, ...)
214256829Snp{
215256829Snp	va_list ap;
216256829Snp
217256829Snp	va_start(ap, fmt);
218256829Snp	vtprintf(cookie, -1, fmt, ap);
219256829Snp	va_end(ap);
220256829Snp}
221256829Snp
222256829Snpint
223256829Snpkrping_sigpending(void)
224256829Snp{
225256829Snp
226256829Snp	return (SIGPENDING(curthread));
227256829Snp}
228256829Snp
229256829SnpDEV_MODULE(krping, krping_loader, NULL);
230256829SnpMODULE_DEPEND(krping, ibcore, 1, 1, 1);
231