mirror of
https://git.FreeBSD.org/src.git
synced 2024-11-27 08:00:11 +00:00
Convert the snp(4) driver to use cdevpriv.
Now we have a single /dev/snp device node, which can be opened by watch(8) multiple times. Even though snp(4) will be dead as of next week, it's nice having this in SVN, because: - We may want to MFC it to RELENG_7. - By the time we fix snp(4) again, it's already there, existing watch(8) binaries should already work. Just like bpf(4), I'm adding a symlink from snp0 to snp to remain binary compatible.
This commit is contained in:
parent
854d77bdd6
commit
2e37c8eacb
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=181755
@ -16,8 +16,8 @@
|
||||
.Ft int
|
||||
.Fn ioctl fd FIONREAD &result
|
||||
.Sh DESCRIPTION
|
||||
.Pa /dev/snp?
|
||||
are snoop devices which allow users to attach to any tty
|
||||
.Pa /dev/snp
|
||||
is a snoop device which allows users to attach to any tty
|
||||
and watch activities on it.
|
||||
The kernel must be compiled with
|
||||
.Cd "device snp" ,
|
||||
|
@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$");
|
||||
static l_close_t snplclose;
|
||||
static l_write_t snplwrite;
|
||||
static d_open_t snpopen;
|
||||
static d_close_t snpclose;
|
||||
static d_read_t snpread;
|
||||
static d_write_t snpwrite;
|
||||
static d_ioctl_t snpioctl;
|
||||
@ -46,7 +45,6 @@ static struct cdevsw snp_cdevsw = {
|
||||
.d_version = D_VERSION,
|
||||
.d_flags = D_PSEUDO | D_NEEDGIANT | D_NEEDMINOR,
|
||||
.d_open = snpopen,
|
||||
.d_close = snpclose,
|
||||
.d_read = snpread,
|
||||
.d_write = snpwrite,
|
||||
.d_ioctl = snpioctl,
|
||||
@ -70,7 +68,6 @@ static struct linesw snpdisc = {
|
||||
*/
|
||||
struct snoop {
|
||||
LIST_ENTRY(snoop) snp_list; /* List glue. */
|
||||
int snp_unit; /* Device number. */
|
||||
struct cdev *snp_target; /* Target tty device. */
|
||||
struct tty *snp_tty; /* Target tty pointer. */
|
||||
u_long snp_len; /* Possible length. */
|
||||
@ -111,13 +108,11 @@ static MALLOC_DEFINE(M_SNP, "snp", "Snoop device data");
|
||||
* module load time.
|
||||
*/
|
||||
static int snooplinedisc;
|
||||
static struct cdev *snoopdev;
|
||||
|
||||
static LIST_HEAD(, snoop) snp_sclist = LIST_HEAD_INITIALIZER(&snp_sclist);
|
||||
static struct clonedevs *snpclones;
|
||||
|
||||
static struct tty *snpdevtotty(struct cdev *dev);
|
||||
static void snp_clone(void *arg, struct ucred *cred, char *name,
|
||||
int namelen, struct cdev **dev);
|
||||
static void snp_detach(void *arg);
|
||||
static int snp_down(struct snoop *snp);
|
||||
static int snp_in(struct snoop *snp, char *buf, int n);
|
||||
@ -220,14 +215,17 @@ snpwrite(struct cdev *dev, struct uio *uio, int flag)
|
||||
int error, i, len;
|
||||
unsigned char c[SNP_INPUT_BUF];
|
||||
|
||||
snp = dev->si_drv1;
|
||||
error = devfs_get_cdevpriv((void **)&snp);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
tp = snp->snp_tty;
|
||||
if (tp == NULL)
|
||||
return (EIO);
|
||||
if ((tp->t_state & TS_SNOOP) && tp->t_line == snooplinedisc)
|
||||
goto tty_input;
|
||||
|
||||
printf("snp%d: attempt to write to bad tty\n", snp->snp_unit);
|
||||
printf("snp: attempt to write to bad tty\n");
|
||||
return (EIO);
|
||||
|
||||
tty_input:
|
||||
@ -255,7 +253,10 @@ snpread(struct cdev *dev, struct uio *uio, int flag)
|
||||
caddr_t from;
|
||||
char *nbuf;
|
||||
|
||||
snp = dev->si_drv1;
|
||||
error = devfs_get_cdevpriv((void **)&snp);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
KASSERT(snp->snp_len + snp->snp_base <= snp->snp_blen,
|
||||
("snoop buffer error"));
|
||||
|
||||
@ -324,12 +325,12 @@ snp_in(struct snoop *snp, char *buf, int n)
|
||||
return (0);
|
||||
|
||||
if (snp->snp_flags & SNOOP_DOWN) {
|
||||
printf("snp%d: more data to down interface\n", snp->snp_unit);
|
||||
printf("snp: more data to down interface\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (snp->snp_flags & SNOOP_OFLOW) {
|
||||
printf("snp%d: buffer overflow\n", snp->snp_unit);
|
||||
printf("snp: buffer overflow\n");
|
||||
/*
|
||||
* On overflow we just repeat the standart close
|
||||
* procedure...yes , this is waste of space but.. Then next
|
||||
@ -387,18 +388,30 @@ snp_in(struct snoop *snp, char *buf, int n)
|
||||
return (n);
|
||||
}
|
||||
|
||||
static void
|
||||
snp_dtor(void *data)
|
||||
{
|
||||
struct snoop *snp = data;
|
||||
|
||||
snp->snp_blen = 0;
|
||||
LIST_REMOVE(snp, snp_list);
|
||||
free(snp->snp_buf, M_SNP);
|
||||
snp->snp_flags &= ~SNOOP_OPEN;
|
||||
snp_detach(snp);
|
||||
}
|
||||
|
||||
static int
|
||||
snpopen(struct cdev *dev, int flag, int mode, struct thread *td)
|
||||
{
|
||||
struct snoop *snp;
|
||||
int error;
|
||||
|
||||
if (dev->si_drv1 == NULL) {
|
||||
dev->si_flags &= ~SI_CHEAPCLONE;
|
||||
dev->si_drv1 = snp = malloc(sizeof(*snp), M_SNP,
|
||||
M_WAITOK | M_ZERO);
|
||||
snp->snp_unit = dev2unit(dev);
|
||||
} else
|
||||
return (EBUSY);
|
||||
snp = malloc(sizeof(*snp), M_SNP, M_WAITOK | M_ZERO);
|
||||
error = devfs_set_cdevpriv(snp, snp_dtor);
|
||||
if (error != 0) {
|
||||
free(snp, M_SNP);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* We intentionally do not OR flags with SNOOP_OPEN, but set them so
|
||||
@ -444,7 +457,7 @@ snp_detach(void *arg)
|
||||
tp->t_state &= ~TS_SNOOP;
|
||||
tp->t_line = snp->snp_olddisc;
|
||||
} else
|
||||
printf("snp%d: bad attached tty data\n", snp->snp_unit);
|
||||
printf("snp: bad attached tty data\n");
|
||||
|
||||
snp->snp_tty = NULL;
|
||||
snp->snp_target = NULL;
|
||||
@ -455,23 +468,6 @@ snp_detach(void *arg)
|
||||
free(snp, M_SNP);
|
||||
}
|
||||
|
||||
static int
|
||||
snpclose(struct cdev *dev, int flags, int fmt, struct thread *td)
|
||||
{
|
||||
struct snoop *snp;
|
||||
|
||||
snp = dev->si_drv1;
|
||||
snp->snp_blen = 0;
|
||||
LIST_REMOVE(snp, snp_list);
|
||||
free(snp->snp_buf, M_SNP);
|
||||
snp->snp_flags &= ~SNOOP_OPEN;
|
||||
dev->si_drv1 = NULL;
|
||||
snp_detach(snp);
|
||||
destroy_dev_sched(dev);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
snp_down(struct snoop *snp)
|
||||
{
|
||||
@ -495,9 +491,12 @@ snpioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags,
|
||||
struct tty *tp;
|
||||
struct cdev *tdev;
|
||||
struct file *fp;
|
||||
int s;
|
||||
int error, s;
|
||||
|
||||
error = devfs_get_cdevpriv((void **)&snp);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
snp = dev->si_drv1;
|
||||
switch (cmd) {
|
||||
case SNPSTTY:
|
||||
s = *(int *)data;
|
||||
@ -587,7 +586,10 @@ snppoll(struct cdev *dev, int events, struct thread *td)
|
||||
struct snoop *snp;
|
||||
int revents;
|
||||
|
||||
snp = dev->si_drv1;
|
||||
if (devfs_get_cdevpriv((void **)&snp) != 0)
|
||||
return (events &
|
||||
(POLLHUP|POLLIN|POLLRDNORM|POLLOUT|POLLWRNORM));
|
||||
|
||||
revents = 0;
|
||||
/*
|
||||
* If snoop is down, we don't want to poll() forever so we return 1.
|
||||
@ -603,44 +605,22 @@ snppoll(struct cdev *dev, int events, struct thread *td)
|
||||
return (revents);
|
||||
}
|
||||
|
||||
static void
|
||||
snp_clone(void *arg, struct ucred *cred, char *name, int namelen,
|
||||
struct cdev **dev)
|
||||
{
|
||||
int u, i;
|
||||
|
||||
if (*dev != NULL)
|
||||
return;
|
||||
if (dev_stdclone(name, NULL, "snp", &u) != 1)
|
||||
return;
|
||||
i = clone_create(&snpclones, &snp_cdevsw, &u, dev, 0);
|
||||
if (i)
|
||||
*dev = make_dev_credf(MAKEDEV_REF, &snp_cdevsw, unit2minor(u),
|
||||
NULL, UID_ROOT, GID_WHEEL, 0600, "snp%d", u);
|
||||
if (*dev != NULL) {
|
||||
(*dev)->si_flags |= SI_CHEAPCLONE;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
snp_modevent(module_t mod, int type, void *data)
|
||||
{
|
||||
static eventhandler_tag eh_tag;
|
||||
|
||||
switch (type) {
|
||||
case MOD_LOAD:
|
||||
/* XXX error checking. */
|
||||
clone_setup(&snpclones);
|
||||
eh_tag = EVENTHANDLER_REGISTER(dev_clone, snp_clone, 0, 1000);
|
||||
snooplinedisc = ldisc_register(LDISC_LOAD, &snpdisc);
|
||||
snoopdev = make_dev(&snp_cdevsw, 0, UID_ROOT, GID_WHEEL,
|
||||
0600, "snp");
|
||||
/* For compatibility */
|
||||
make_dev_alias(snoopdev, "snp0");
|
||||
break;
|
||||
case MOD_UNLOAD:
|
||||
if (!LIST_EMPTY(&snp_sclist))
|
||||
return (EBUSY);
|
||||
EVENTHANDLER_DEREGISTER(dev_clone, eh_tag);
|
||||
drain_dev_clone_events();
|
||||
clone_cleanup(&snpclones);
|
||||
destroy_dev_drain(&snp_cdevsw);
|
||||
destroy_dev(snoopdev);
|
||||
ldisc_deregister(snooplinedisc);
|
||||
break;
|
||||
default:
|
||||
|
@ -152,30 +152,21 @@ fatal(int error, const char *buf)
|
||||
static int
|
||||
open_snp(void)
|
||||
{
|
||||
char snp[] = {_PATH_DEV "snpXXX"};
|
||||
int f, mode, pos, c;
|
||||
int f, mode;
|
||||
|
||||
pos = strlen(snp) - 3;
|
||||
if (opt_write)
|
||||
mode = O_RDWR;
|
||||
else
|
||||
mode = O_RDONLY;
|
||||
|
||||
if (opt_snpdev == NULL)
|
||||
for (c = 0; c <= 999; c++) {
|
||||
snprintf(snp+pos, 4, "%d", c);
|
||||
if ((f = open(snp, mode)) < 0) {
|
||||
if (errno == EBUSY)
|
||||
continue;
|
||||
err(1, "open %s", snp);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
f = open(_PATH_DEV "snp", mode);
|
||||
else
|
||||
if ((f = open(opt_snpdev, mode)) != -1)
|
||||
return (f);
|
||||
fatal(EX_OSFILE, "cannot open snoop device");
|
||||
return (0);
|
||||
f = open(opt_snpdev, mode);
|
||||
if (f == -1)
|
||||
fatal(EX_OSFILE, "cannot open snoop device");
|
||||
|
||||
return (f);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user