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: stable/11/sys/contrib/rdma/krping/krping_dev.c 353181 2019-10-07 08:28:55Z hselasky $"); 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 33SYSCTL_NODE(_dev, OID_AUTO, krping, CTLFLAG_RW, 0, "kernel rping module"); 34 35int krping_debug = 0; 36SYSCTL_INT(_dev_krping, OID_AUTO, debug, CTLFLAG_RW, &krping_debug, 0 , ""); 37 38/* Function prototypes */ 39static d_open_t krping_open; 40static d_close_t krping_close; 41static d_read_t krping_read; 42static d_write_t krping_write; 43static d_purge_t krping_purge; 44 45/* Character device entry points */ 46static 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 56typedef struct s_krping { 57 char msg[BUFFERSIZE]; 58 int len; 59} krping_t; 60 61struct stats_list_entry { 62 STAILQ_ENTRY(stats_list_entry) link; 63 struct krping_stats *stats; 64}; 65STAILQ_HEAD(stats_list, stats_list_entry); 66 67/* vars */ 68static struct cdev *krping_dev; 69 70static int 71krping_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 93static int 94krping_open(struct cdev *dev, int oflags, int devtype, struct thread *p) 95{ 96 97 return (0); 98} 99 100static int 101krping_close(struct cdev *dev, int fflag, int devtype, struct thread *p) 102{ 103 104 return 0; 105} 106 107static void 108krping_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 127static int 128krping_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 167static int 168krping_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); 210done: 211 free(krpingmsg, M_DEVBUF); 212 return(err); 213} 214 215static void 216krping_purge(struct cdev *dev __unused) 217{ 218 219 krping_cancel_all(); 220} 221 222int 223krping_sigpending(void) 224{ 225 226 return (SIGPENDING(curthread)); 227} 228 229DEV_MODULE(krping, krping_loader, NULL); 230MODULE_DEPEND(krping, ibcore, 1, 1, 1); 231