1 /*
2 * This code lifted from:
3 * Simple `echo' pseudo-device KLD
4 * Murray Stokely
5 * Converted to 5.X by Søren (Xride) Straarup
6 */
7
8 /*
9 * /bin/echo "server,port=9999,addr=192.168.69.142,validate" > /dev/krping
10 * /bin/echo "client,port=9999,addr=192.168.69.142,validate" > /dev/krping
11 */
12
13 #include <sys/cdefs.h>
14 __FBSDID("$FreeBSD$");
15
16 #include <sys/types.h>
17 #include <sys/param.h> /* defines used in kernel.h and module.h */
18 #include <sys/module.h>
19 #include <sys/systm.h> /* uprintf */
20 #include <sys/errno.h>
21 #include <sys/kernel.h> /* types used in module initialization */
22 #include <sys/conf.h> /* cdevsw struct */
23 #include <sys/uio.h> /* uio struct */
24 #include <sys/malloc.h>
25 #include <sys/proc.h>
26 #include <sys/sysctl.h>
27 #include <machine/stdarg.h>
28
29 #include "krping.h"
30
31 #define BUFFERSIZE 512
32
33 SYSCTL_NODE(_dev, OID_AUTO, krping, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
34 "kernel rping module");
35
36 int krping_debug = 0;
37 SYSCTL_INT(_dev_krping, OID_AUTO, debug, CTLFLAG_RW, &krping_debug, 0 , "");
38
39 /* Function prototypes */
40 static d_open_t krping_open;
41 static d_close_t krping_close;
42 static d_read_t krping_read;
43 static d_write_t krping_write;
44 static d_purge_t krping_purge;
45
46 /* Character device entry points */
47 static struct cdevsw krping_cdevsw = {
48 .d_version = D_VERSION,
49 .d_open = krping_open,
50 .d_close = krping_close,
51 .d_read = krping_read,
52 .d_write = krping_write,
53 .d_purge = krping_purge,
54 .d_name = "krping",
55 };
56
57 typedef struct s_krping {
58 char msg[BUFFERSIZE];
59 int len;
60 } krping_t;
61
62 struct stats_list_entry {
63 STAILQ_ENTRY(stats_list_entry) link;
64 struct krping_stats *stats;
65 };
66 STAILQ_HEAD(stats_list, stats_list_entry);
67
68 /* vars */
69 static struct cdev *krping_dev;
70
71 static int
krping_loader(struct module * m,int what,void * arg)72 krping_loader(struct module *m, int what, void *arg)
73 {
74 int err = 0;
75
76 switch (what) {
77 case MOD_LOAD: /* kldload */
78 krping_dev = make_dev(&krping_cdevsw, 0, UID_ROOT, GID_WHEEL,
79 0600, "krping");
80 printf("Krping device loaded.\n");
81 break;
82 case MOD_UNLOAD:
83 destroy_dev(krping_dev);
84 printf("Krping device unloaded.\n");
85 break;
86 default:
87 err = EOPNOTSUPP;
88 break;
89 }
90
91 return (err);
92 }
93
94 static int
krping_open(struct cdev * dev,int oflags,int devtype,struct thread * p)95 krping_open(struct cdev *dev, int oflags, int devtype, struct thread *p)
96 {
97
98 return (0);
99 }
100
101 static int
krping_close(struct cdev * dev,int fflag,int devtype,struct thread * p)102 krping_close(struct cdev *dev, int fflag, int devtype, struct thread *p)
103 {
104
105 return 0;
106 }
107
108 static void
krping_copy_stats(struct krping_stats * stats,void * arg)109 krping_copy_stats(struct krping_stats *stats, void *arg)
110 {
111 struct stats_list_entry *s;
112 struct stats_list *list = arg;
113
114 s = malloc(sizeof(*s), M_DEVBUF, M_NOWAIT | M_ZERO);
115 if (s == NULL)
116 return;
117 if (stats != NULL) {
118 s->stats = malloc(sizeof(*stats), M_DEVBUF, M_NOWAIT | M_ZERO);
119 if (s->stats == NULL) {
120 free(s, M_DEVBUF);
121 return;
122 }
123 *s->stats = *stats;
124 }
125 STAILQ_INSERT_TAIL(list, s, link);
126 }
127
128 static int
krping_read(struct cdev * dev,struct uio * uio,int ioflag)129 krping_read(struct cdev *dev, struct uio *uio, int ioflag)
130 {
131 int num = 1;
132 struct stats_list list;
133 struct stats_list_entry *e;
134
135 STAILQ_INIT(&list);
136 krping_walk_cb_list(krping_copy_stats, &list);
137
138 if (STAILQ_EMPTY(&list))
139 return (0);
140
141 uprintf("krping: %4s %10s %10s %10s %10s %10s %10s %10s %10s %10s\n",
142 "num", "device", "snd bytes", "snd msgs", "rcv bytes", "rcv msgs",
143 "wr bytes", "wr msgs", "rd bytes", "rd msgs");
144
145 while (!STAILQ_EMPTY(&list)) {
146 e = STAILQ_FIRST(&list);
147 STAILQ_REMOVE_HEAD(&list, link);
148 if (e->stats == NULL)
149 uprintf("krping: %d listen\n", num);
150 else {
151 struct krping_stats *stats = e->stats;
152
153 uprintf("krping: %4d %10s %10llu %10llu %10llu %10llu "
154 "%10llu %10llu %10llu %10llu\n", num, stats->name,
155 stats->send_bytes, stats->send_msgs,
156 stats->recv_bytes, stats->recv_msgs,
157 stats->write_bytes, stats->write_msgs,
158 stats->read_bytes, stats->read_msgs);
159 free(stats, M_DEVBUF);
160 }
161 num++;
162 free(e, M_DEVBUF);
163 }
164
165 return (0);
166 }
167
168 static int
krping_write(struct cdev * dev,struct uio * uio,int ioflag)169 krping_write(struct cdev *dev, struct uio *uio, int ioflag)
170 {
171 int err = 0;
172 int amt;
173 int remain = BUFFERSIZE;
174 char *cp;
175 krping_t *krpingmsg;
176
177 krpingmsg = malloc(sizeof *krpingmsg, M_DEVBUF, M_WAITOK | M_ZERO);
178 cp = krpingmsg->msg;
179 while (uio->uio_resid) {
180 amt = MIN(uio->uio_resid, remain);
181 if (amt == 0)
182 break;
183
184 /* Copy the string in from user memory to kernel memory */
185 err = uiomove(cp, amt, uio);
186 if (err) {
187 uprintf("Write failed: bad address!\n");
188 goto done;
189 }
190 cp += amt;
191 remain -= amt;
192 }
193
194 if (uio->uio_resid != 0) {
195 uprintf("Message too big. max size is %d!\n", BUFFERSIZE);
196 err = EMSGSIZE;
197 goto done;
198 }
199
200 /* null terminate and remove the \n */
201 cp--;
202 *cp = 0;
203 krpingmsg->len = (unsigned long)(cp - krpingmsg->msg);
204 uprintf("krping: write string = |%s|\n", krpingmsg->msg);
205 err = krping_doit(krpingmsg->msg);
206 done:
207 free(krpingmsg, M_DEVBUF);
208 return(err);
209 }
210
211 static void
krping_purge(struct cdev * dev __unused)212 krping_purge(struct cdev *dev __unused)
213 {
214
215 krping_cancel_all();
216 }
217
218 int
krping_sigpending(void)219 krping_sigpending(void)
220 {
221
222 return (SIGPENDING(curthread));
223 }
224
225 DEV_MODULE(krping, krping_loader, NULL);
226 MODULE_DEPEND(krping, ibcore, 1, 1, 1);
227