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