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