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 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 95 krping_open(struct cdev *dev, int oflags, int devtype, struct thread *p) 96 { 97 98 return (0); 99 } 100 101 static int 102 krping_close(struct cdev *dev, int fflag, int devtype, struct thread *p) 103 { 104 105 return 0; 106 } 107 108 static void 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 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 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 212 krping_purge(struct cdev *dev __unused) 213 { 214 215 krping_cancel_all(); 216 } 217 218 int 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