xref: /onnv-gate/usr/src/uts/common/inet/ip/ipdrop.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <sys/types.h>
30*0Sstevel@tonic-gate #include <sys/stream.h>
31*0Sstevel@tonic-gate #include <sys/strsun.h>
32*0Sstevel@tonic-gate #include <sys/sunddi.h>
33*0Sstevel@tonic-gate #include <sys/kstat.h>
34*0Sstevel@tonic-gate #include <sys/kmem.h>
35*0Sstevel@tonic-gate #include <net/pfkeyv2.h>
36*0Sstevel@tonic-gate #include <inet/common.h>
37*0Sstevel@tonic-gate #include <inet/ip.h>
38*0Sstevel@tonic-gate #include <inet/ip6.h>
39*0Sstevel@tonic-gate #include <inet/ipsec_info.h>
40*0Sstevel@tonic-gate #include <inet/ipdrop.h>
41*0Sstevel@tonic-gate 
42*0Sstevel@tonic-gate /*
43*0Sstevel@tonic-gate  * Packet drop facility.
44*0Sstevel@tonic-gate  */
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate kstat_t *ip_drop_kstat;
47*0Sstevel@tonic-gate struct ip_dropstats *ip_drop_types;
48*0Sstevel@tonic-gate 
49*0Sstevel@tonic-gate /*
50*0Sstevel@tonic-gate  * Initialize drop facility kstats.
51*0Sstevel@tonic-gate  */
52*0Sstevel@tonic-gate void
53*0Sstevel@tonic-gate ip_drop_init(void)
54*0Sstevel@tonic-gate {
55*0Sstevel@tonic-gate 	ip_drop_kstat = kstat_create("ip", 0, "ipdrop", "net",
56*0Sstevel@tonic-gate 	    KSTAT_TYPE_NAMED, sizeof (*ip_drop_types) / sizeof (kstat_named_t),
57*0Sstevel@tonic-gate 	    KSTAT_FLAG_PERSISTENT);
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate 	if (ip_drop_kstat == NULL)
60*0Sstevel@tonic-gate 		return;
61*0Sstevel@tonic-gate 
62*0Sstevel@tonic-gate 	ip_drop_types = ip_drop_kstat->ks_data;
63*0Sstevel@tonic-gate 
64*0Sstevel@tonic-gate 	/* TCP IPsec drop statistics. */
65*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_tcp_clear, "tcp_clear", KSTAT_DATA_UINT64);
66*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_tcp_secure, "tcp_secure", KSTAT_DATA_UINT64);
67*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_tcp_mismatch, "tcp_mismatch",
68*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
69*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_tcp_ipsec_alloc, "tcp_ipsec_alloc",
70*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
71*0Sstevel@tonic-gate 
72*0Sstevel@tonic-gate 	/* SADB-specific drop statistics. */
73*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_sadb_inlarval_timeout,
74*0Sstevel@tonic-gate 	    "sadb_inlarval_timeout", KSTAT_DATA_UINT64);
75*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_sadb_inlarval_replace,
76*0Sstevel@tonic-gate 	    "sadb_inlarval_replace", KSTAT_DATA_UINT64);
77*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_sadb_acquire_nomem,
78*0Sstevel@tonic-gate 	    "sadb_acquire_nomem", KSTAT_DATA_UINT64);
79*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_sadb_acquire_toofull,
80*0Sstevel@tonic-gate 	    "sadb_acquire_toofull", KSTAT_DATA_UINT64);
81*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_sadb_acquire_timeout,
82*0Sstevel@tonic-gate 	    "sadb_acquire_timeout", KSTAT_DATA_UINT64);
83*0Sstevel@tonic-gate 
84*0Sstevel@tonic-gate 	/* SPD drop statistics. */
85*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_spd_ahesp_diffid, "spd_ahesp_diffid",
86*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
87*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_spd_loopback_mismatch,
88*0Sstevel@tonic-gate 	    "spd_loopback_mismatch", KSTAT_DATA_UINT64);
89*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_spd_explicit, "spd_explicit",
90*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
91*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_spd_got_secure, "spd_got_secure",
92*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
93*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_spd_got_clear, "spd_got_clear",
94*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
95*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_spd_bad_ahalg, "spd_bad_ahalg",
96*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
97*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_spd_got_ah, "spd_got_ah", KSTAT_DATA_UINT64);
98*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_spd_bad_espealg, "spd_bad_espealg",
99*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
100*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_spd_bad_espaalg, "spd_bad_espaalg",
101*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
102*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_spd_got_esp, "spd_got_esp",
103*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
104*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_spd_got_selfencap, "spd_got_selfencap",
105*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
106*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_spd_bad_selfencap, "spd_bad_selfencap",
107*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
108*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_spd_nomem, "spd_nomem", KSTAT_DATA_UINT64);
109*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_spd_ah_badid, "spd_ah_badid",
110*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
111*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_spd_esp_badid, "spd_esp_badid",
112*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
113*0Sstevel@tonic-gate 
114*0Sstevel@tonic-gate 	/* ESP-specific drop statistics. */
115*0Sstevel@tonic-gate 
116*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_esp_nomem, "esp_nomem", KSTAT_DATA_UINT64);
117*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_esp_no_sa, "esp_no_sa", KSTAT_DATA_UINT64);
118*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_esp_early_replay, "esp_early_replay",
119*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
120*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_esp_replay, "esp_replay", KSTAT_DATA_UINT64);
121*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_esp_bytes_expire, "esp_bytes_expire",
122*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
123*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_esp_bad_padlen, "esp_bad_padlen",
124*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
125*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_esp_bad_padding, "esp_bad_padding",
126*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
127*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_esp_bad_auth, "esp_bad_auth",
128*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
129*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_esp_crypto_failed, "esp_crypto_failed",
130*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
131*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_esp_icmp, "esp_icmp", KSTAT_DATA_UINT64);
132*0Sstevel@tonic-gate 
133*0Sstevel@tonic-gate 	/* AH-specific drop statistics. */
134*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_ah_nomem, "ah_nomem", KSTAT_DATA_UINT64);
135*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_ah_bad_v6_hdrs, "ah_bad_v6_hdrs",
136*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
137*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_ah_bad_v4_opts, "ah_bad_v4_opts",
138*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
139*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_ah_no_sa, "ah_no_sa", KSTAT_DATA_UINT64);
140*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_ah_bad_length, "ah_bad_length",
141*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
142*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_ah_bad_auth, "ah_bad_auth",
143*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
144*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_ah_crypto_failed, "ah_crypto_failed",
145*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
146*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_ah_early_replay, "ah_early_replay",
147*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
148*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_ah_replay, "ah_replay", KSTAT_DATA_UINT64);
149*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_ah_bytes_expire, "ah_bytes_expire",
150*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
151*0Sstevel@tonic-gate 
152*0Sstevel@tonic-gate 	/* IP-specific drop statistics. */
153*0Sstevel@tonic-gate 	kstat_named_init(&ipdrops_ip_ipsec_not_loaded, "ip_ipsec_not_loaded",
154*0Sstevel@tonic-gate 	    KSTAT_DATA_UINT64);
155*0Sstevel@tonic-gate 
156*0Sstevel@tonic-gate 	kstat_install(ip_drop_kstat);
157*0Sstevel@tonic-gate }
158*0Sstevel@tonic-gate 
159*0Sstevel@tonic-gate void
160*0Sstevel@tonic-gate ip_drop_destroy(void)
161*0Sstevel@tonic-gate {
162*0Sstevel@tonic-gate 	kstat_delete(ip_drop_kstat);
163*0Sstevel@tonic-gate }
164*0Sstevel@tonic-gate 
165*0Sstevel@tonic-gate /*
166*0Sstevel@tonic-gate  * Register a packet dropper.
167*0Sstevel@tonic-gate  */
168*0Sstevel@tonic-gate void
169*0Sstevel@tonic-gate ip_drop_register(ipdropper_t *ipd, char *name)
170*0Sstevel@tonic-gate {
171*0Sstevel@tonic-gate 	if (ipd->ipd_name != NULL) {
172*0Sstevel@tonic-gate 		cmn_err(CE_WARN,
173*0Sstevel@tonic-gate 		    "ip_drop_register: ipdropper %s already registered with %s",
174*0Sstevel@tonic-gate 		    name, ipd->ipd_name);
175*0Sstevel@tonic-gate 		return;
176*0Sstevel@tonic-gate 	}
177*0Sstevel@tonic-gate 
178*0Sstevel@tonic-gate 	/* Assume that name is reasonable in length.  This isn't user-land. */
179*0Sstevel@tonic-gate 	ipd->ipd_name = kmem_alloc(strlen(name) + 1, KM_SLEEP);
180*0Sstevel@tonic-gate 	(void) strcpy(ipd->ipd_name, name);
181*0Sstevel@tonic-gate }
182*0Sstevel@tonic-gate 
183*0Sstevel@tonic-gate /*
184*0Sstevel@tonic-gate  * Un-register a packet dropper.
185*0Sstevel@tonic-gate  */
186*0Sstevel@tonic-gate void
187*0Sstevel@tonic-gate ip_drop_unregister(ipdropper_t *ipd)
188*0Sstevel@tonic-gate {
189*0Sstevel@tonic-gate 	kmem_free(ipd->ipd_name, strlen(ipd->ipd_name) + 1);
190*0Sstevel@tonic-gate 
191*0Sstevel@tonic-gate 	ipd->ipd_name = NULL;
192*0Sstevel@tonic-gate }
193*0Sstevel@tonic-gate 
194*0Sstevel@tonic-gate /*
195*0Sstevel@tonic-gate  * Actually drop a packet.  Many things could happen here, but at the least,
196*0Sstevel@tonic-gate  * the packet will be freemsg()ed.
197*0Sstevel@tonic-gate  */
198*0Sstevel@tonic-gate /* ARGSUSED */
199*0Sstevel@tonic-gate void
200*0Sstevel@tonic-gate ip_drop_packet(mblk_t *mp, boolean_t inbound, ill_t *arriving,
201*0Sstevel@tonic-gate     ire_t *outbound_ire, struct kstat_named *counter, ipdropper_t *who_called)
202*0Sstevel@tonic-gate {
203*0Sstevel@tonic-gate 	mblk_t *ipsec_mp = NULL;
204*0Sstevel@tonic-gate 	ipsec_in_t *ii = NULL;
205*0Sstevel@tonic-gate 	ipsec_out_t *io = NULL;
206*0Sstevel@tonic-gate 	ipsec_info_t *in;
207*0Sstevel@tonic-gate 	uint8_t vers;
208*0Sstevel@tonic-gate 
209*0Sstevel@tonic-gate 	if (mp == NULL) {
210*0Sstevel@tonic-gate 		/*
211*0Sstevel@tonic-gate 		 * Return immediately - NULL packets should not affect any
212*0Sstevel@tonic-gate 		 * statistics.
213*0Sstevel@tonic-gate 		 */
214*0Sstevel@tonic-gate 		return;
215*0Sstevel@tonic-gate 	}
216*0Sstevel@tonic-gate 
217*0Sstevel@tonic-gate 	if (DB_TYPE(mp) == M_CTL) {
218*0Sstevel@tonic-gate 		in = (ipsec_info_t *)mp->b_rptr;
219*0Sstevel@tonic-gate 
220*0Sstevel@tonic-gate 		if (in->ipsec_info_type == IPSEC_IN)
221*0Sstevel@tonic-gate 			ii = (ipsec_in_t *)in;
222*0Sstevel@tonic-gate 		else if (in->ipsec_info_type == IPSEC_OUT)
223*0Sstevel@tonic-gate 			io = (ipsec_out_t *)in;
224*0Sstevel@tonic-gate 
225*0Sstevel@tonic-gate 		/* See if this is an ICMP packet (check for v4/v6). */
226*0Sstevel@tonic-gate 		vers = (*mp->b_rptr) >> 4;
227*0Sstevel@tonic-gate 		if (vers != IPV4_VERSION && vers != IPV6_VERSION) {
228*0Sstevel@tonic-gate 			/*
229*0Sstevel@tonic-gate 			 * If not, it's some other sort of M_CTL to be freed.
230*0Sstevel@tonic-gate 			 * For now, treat it like an ordinary packet.
231*0Sstevel@tonic-gate 			 */
232*0Sstevel@tonic-gate 			ipsec_mp = mp;
233*0Sstevel@tonic-gate 			mp = mp->b_cont;
234*0Sstevel@tonic-gate 		}
235*0Sstevel@tonic-gate 	}
236*0Sstevel@tonic-gate 
237*0Sstevel@tonic-gate 	/* Reality checks */
238*0Sstevel@tonic-gate 	if (inbound && io != NULL)
239*0Sstevel@tonic-gate 		cmn_err(CE_WARN,
240*0Sstevel@tonic-gate 		    "ip_drop_packet: inbound packet with IPSEC_OUT");
241*0Sstevel@tonic-gate 
242*0Sstevel@tonic-gate 	if (outbound_ire != NULL && ii != NULL)
243*0Sstevel@tonic-gate 		cmn_err(CE_WARN,
244*0Sstevel@tonic-gate 		    "ip_drop_packet: outbound packet with IPSEC_IN");
245*0Sstevel@tonic-gate 
246*0Sstevel@tonic-gate 	/* At this point, mp always points to the data. */
247*0Sstevel@tonic-gate 	/*
248*0Sstevel@tonic-gate 	 * Can't make the assertion yet - It could be an inbound ICMP
249*0Sstevel@tonic-gate 	 * message, which is M_CTL but with data in it.
250*0Sstevel@tonic-gate 	 */
251*0Sstevel@tonic-gate 	/* ASSERT(mp->b_datap->db_type == M_DATA); */
252*0Sstevel@tonic-gate 
253*0Sstevel@tonic-gate 	/* Increment the bean counter, if available. */
254*0Sstevel@tonic-gate 	if (counter != NULL) {
255*0Sstevel@tonic-gate 		switch (counter->data_type) {
256*0Sstevel@tonic-gate 		case KSTAT_DATA_INT32:
257*0Sstevel@tonic-gate 			counter->value.i32++;
258*0Sstevel@tonic-gate 			break;
259*0Sstevel@tonic-gate 		case KSTAT_DATA_UINT32:
260*0Sstevel@tonic-gate 			counter->value.ui32++;
261*0Sstevel@tonic-gate 			break;
262*0Sstevel@tonic-gate 		case KSTAT_DATA_INT64:
263*0Sstevel@tonic-gate 			counter->value.i64++;
264*0Sstevel@tonic-gate 			break;
265*0Sstevel@tonic-gate 		case KSTAT_DATA_UINT64:
266*0Sstevel@tonic-gate 			counter->value.ui64++;
267*0Sstevel@tonic-gate 			break;
268*0Sstevel@tonic-gate 		/* Other types we can't handle for now. */
269*0Sstevel@tonic-gate 		}
270*0Sstevel@tonic-gate 
271*0Sstevel@tonic-gate 		/* TODO?  Copy out kstat name for use in logging. */
272*0Sstevel@tonic-gate 	}
273*0Sstevel@tonic-gate 
274*0Sstevel@tonic-gate 	/* TODO: log the packet details if logging is called for. */
275*0Sstevel@tonic-gate 	/* TODO: queue the packet onto a snoop-friendly queue. */
276*0Sstevel@tonic-gate 
277*0Sstevel@tonic-gate 	/* If I haven't queued the packet or some such nonsense, free it. */
278*0Sstevel@tonic-gate 	if (ipsec_mp != NULL)
279*0Sstevel@tonic-gate 		freeb(ipsec_mp);
280*0Sstevel@tonic-gate 	freemsg(mp);
281*0Sstevel@tonic-gate }
282