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 33SYSCTL_NODE(_dev, OID_AUTO, krping, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 34 "kernel rping module"); 35 36int krping_debug = 0; 37SYSCTL_INT(_dev_krping, OID_AUTO, debug, CTLFLAG_RW, &krping_debug, 0 , ""); 38 39/* Function prototypes */ 40static d_open_t krping_open; 41static d_close_t krping_close; 42static d_read_t krping_read; 43static d_write_t krping_write; 44static d_purge_t krping_purge; 45 46/* Character device entry points */ 47static 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 57typedef struct s_krping { 58 char msg[BUFFERSIZE]; 59 int len; 60} krping_t; 61 62struct stats_list_entry { 63 STAILQ_ENTRY(stats_list_entry) link; 64 struct krping_stats *stats; 65}; 66STAILQ_HEAD(stats_list, stats_list_entry); 67 68/* vars */ 69static struct cdev *krping_dev; 70 71static int 72krping_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 94static int 95krping_open(struct cdev *dev, int oflags, int devtype, struct thread *p) 96{ 97 98 return (0); 99} 100 101static int 102krping_close(struct cdev *dev, int fflag, int devtype, struct thread *p) 103{ 104 105 return 0; 106} 107 108static void 109krping_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 128static int 129krping_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 168static int 169krping_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 if (!krpingmsg) { 179 uprintf("Could not malloc mem!\n"); 180 return ENOMEM; 181 } 182 183 cp = krpingmsg->msg; 184 while (uio->uio_resid) { 185 amt = MIN(uio->uio_resid, remain); 186 if (amt == 0) 187 break; 188 189 /* Copy the string in from user memory to kernel memory */ 190 err = uiomove(cp, amt, uio); 191 if (err) { 192 uprintf("Write failed: bad address!\n"); 193 goto done; 194 } 195 cp += amt; 196 remain -= amt; 197 } 198 199 if (uio->uio_resid != 0) { 200 uprintf("Message too big. max size is %d!\n", BUFFERSIZE); 201 err = EMSGSIZE; 202 goto done; 203 } 204 205 /* null terminate and remove the \n */ 206 cp--; 207 *cp = 0; 208 krpingmsg->len = (unsigned long)(cp - krpingmsg->msg); 209 uprintf("krping: write string = |%s|\n", krpingmsg->msg); 210 err = krping_doit(krpingmsg->msg); 211done: 212 free(krpingmsg, M_DEVBUF); 213 return(err); 214} 215 216static void 217krping_purge(struct cdev *dev __unused) 218{ 219 220 krping_cancel_all(); 221} 222 223int 224krping_sigpending(void) 225{ 226 227 return (SIGPENDING(curthread)); 228} 229 230DEV_MODULE(krping, krping_loader, NULL); 231MODULE_DEPEND(krping, ibcore, 1, 1, 1); 232