summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/inet/sockmods/datafilt.c
blob: 6e1171de46a0e9eb1daa11410a26d49c6374b286 (plain)
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*
 * This file and its contents are supplied under the terms of the
 * Common Development and Distribution License ("CDDL"), version 1.0.
 * You may only use this file in accordance with the terms of version
 * 1.0 of the CDDL.
 *
 * A full copy of the text of the CDDL should have accompanied this
 * source.  A copy of the CDDL is also available via the Internet at
 * http://www.illumos.org/license/CDDL.
 */

/*
 * Copyright (c) 2012, OmniTI Computer Consulting, Inc. All rights reserved.
 */

/*
 * This file implements a socketfilter used to deter TCP connections.
 * To defer a connection means to delay the return of accept(3SOCKET)
 * until at least one byte is ready to be read(2). This filter may be
 * applied automatically or programmatically through the use of
 * soconfig(1M) and setsockopt(3SOCKET).
 */

#include <sys/kmem.h>
#include <sys/systm.h>
#include <sys/stropts.h>
#include <sys/strsun.h>
#include <sys/socketvar.h>
#include <sys/sockfilter.h>
#include <sys/note.h>
#include <sys/taskq.h>

#define	DATAFILT_MODULE "datafilt"

static struct modlmisc dataf_modlmisc = {
	&mod_miscops,
	"Kernel data-ready socket filter"
};

static struct modlinkage dataf_modlinkage = {
	MODREV_1,
	&dataf_modlmisc,
	NULL
};

static sof_rval_t
dataf_attach_passive_cb(sof_handle_t handle, sof_handle_t ph,
    void *parg, struct sockaddr *laddr, socklen_t laddrlen,
    struct sockaddr *faddr, socklen_t faddrlen, void **cookiep)
{
	_NOTE(ARGUNUSED(handle, ph, parg, laddr, laddrlen, faddr, faddrlen,
	cookiep));
	return (SOF_RVAL_DEFER);
}

static void
dataf_detach_cb(sof_handle_t handle, void *cookie, cred_t *cr)
{
	_NOTE(ARGUNUSED(handle, cookie, cr));
}

static mblk_t *
dataf_data_in_cb(sof_handle_t handle, void *cookie, mblk_t *mp, int flags,
    size_t *lenp)
{
	_NOTE(ARGUNUSED(cookie, flags, lenp));

	if (mp != NULL && MBLKL(mp) > 0) {
		sof_newconn_ready(handle);
		sof_bypass(handle);
	}

	return (mp);
}

static sof_ops_t dataf_ops = {
	.sofop_attach_passive = dataf_attach_passive_cb,
	.sofop_detach = dataf_detach_cb,
	.sofop_data_in = dataf_data_in_cb
};

int
_init(void)
{
	int err;

	/*
	 * This module is safe to attach even after some preliminary socket
	 * setup calls have taken place. See the comment for SOF_ATT_SAFE.
	 */
	err = sof_register(SOF_VERSION, DATAFILT_MODULE, &dataf_ops,
	    SOF_ATT_SAFE);
	if (err != 0)
		return (err);
	if ((err = mod_install(&dataf_modlinkage)) != 0)
		(void) sof_unregister(DATAFILT_MODULE);

	return (err);
}

int
_fini(void)
{
	int err;

	if ((err = sof_unregister(DATAFILT_MODULE)) != 0)
		return (err);

	return (mod_remove(&dataf_modlinkage));
}

int
_info(struct modinfo *modinfop)
{
	return (mod_info(&dataf_modlinkage, modinfop));
}