summaryrefslogtreecommitdiff
path: root/contrib/ipfilter/ipl_ldev.c
blob: a2893257e72e16d1aafb3937e3903729b5d00b27 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/*
 * (C)opyright 1993,1994,1995 by Darren Reed.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that this notice is preserved and due credit is given
 * to the original author and the contributors.
 */

/*
 * routines below for saving IP headers to buffer
 */
int iplopen(struct inode * inode, struct file * filp)
{
	u_int	min = MINOR(inode->i_rdev);

	if (flags & FWRITE)
		return ENXIO;
	if (min)
		return ENXIO;
	iplbusy++;
	return 0;
}


int iplclose(struct inode * inode, struct file * filp)
{
	u_int	min = MINOR(inode->i_rdev);

	if (min)
		return ENXIO;
	iplbusy--;
	return 0;
}


/*
 * iplread/ipllog
 * all three of these must operate with at least splnet() lest they be
 * called during packet processing and cause an inconsistancy to appear in
 * the filter lists.
 */
int iplread(struct inode *inode, struct file *file, char *buf, int count)
{
	register int	ret, s;
	register size_t	sz, sx;
	int error;

	if (!uio->uio_resid)
		return 0;
	while (!iplused) {
		error = SLEEP(iplbuf, "ipl sleep");
		if (error)
			return error;
	}

	SPLNET(s);

	ret = sx = sz = MIN(count, iplused);
	if (iplh < iplt)
		sz = MIN(sz, LOGSIZE - (iplt - iplbuf));
	sx -= sz;

	memcpy_tofs(buf, iplt, sz);
	buf += sz;
	iplt += sz;
	iplused -= sz;
	if ((iplh < iplt) && (iplt == iplbuf + LOGSIZE))
		iplt = iplbuf;

	if (sx) {
		memcpy_tofs(buf, iplt, sx);
		ret += sx;
		iplt += sx;
		iplused -= sx;
		if ((iplh < iplt) && (iplt == iplbuf + LOGSIZE))
			iplt = iplbuf;
	}
	if (!iplused)	/* minimise wrapping around the end */
		iplh = iplt = iplbuf;

	SPLX(s);
	return ret;
}