4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/types.h>
27 #include <sys/stream.h>
28 #include <sys/strsun.h>
29 #include <sys/sunddi.h>
30 #include <sys/kstat.h>
33 #include <net/pfkeyv2.h>
34 #include <inet/common.h>
37 #include <inet/ipsec_impl.h>
38 #include <inet/ipdrop.h>
41 * Packet drop facility.
45 * Initialize drop facility kstats.
48 ip_drop_init(ipsec_stack_t
*ipss
)
50 ipss
->ipsec_ip_drop_kstat
= kstat_create_netstack("ip", 0, "ipdrop",
51 "net", KSTAT_TYPE_NAMED
,
52 sizeof (struct ip_dropstats
) / sizeof (kstat_named_t
),
53 KSTAT_FLAG_PERSISTENT
, ipss
->ipsec_netstack
->netstack_stackid
);
55 if (ipss
->ipsec_ip_drop_kstat
== NULL
||
56 ipss
->ipsec_ip_drop_kstat
->ks_data
== NULL
)
60 * Note: here ipss->ipsec_ip_drop_types is initialized, however,
61 * if the previous kstat_create_netstack failed, it will remain
62 * NULL. Note this is done for all stack instances, so it *could*
63 * be NULL. Hence a non-NULL checking is added where
64 * ipss->ipsec_ip_drop_types is used. This checking is hidden in
67 ipss
->ipsec_ip_drop_types
= ipss
->ipsec_ip_drop_kstat
->ks_data
;
69 /* TCP IPsec drop statistics. */
70 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_tcp_clear
,
71 "tcp_clear", KSTAT_DATA_UINT64
);
72 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_tcp_secure
,
73 "tcp_secure", KSTAT_DATA_UINT64
);
74 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_tcp_mismatch
,
75 "tcp_mismatch", KSTAT_DATA_UINT64
);
76 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_tcp_ipsec_alloc
,
77 "tcp_ipsec_alloc", KSTAT_DATA_UINT64
);
79 /* SADB-specific drop statistics. */
80 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_sadb_inlarval_timeout
,
81 "sadb_inlarval_timeout", KSTAT_DATA_UINT64
);
82 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_sadb_inlarval_replace
,
83 "sadb_inlarval_replace", KSTAT_DATA_UINT64
);
84 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_sadb_inidle_overflow
,
85 "sadb_inidle_overflow", KSTAT_DATA_UINT64
);
86 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_sadb_inidle_timeout
,
87 "sadb_inidle_timeout", KSTAT_DATA_UINT64
);
88 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_sadb_acquire_nomem
,
89 "sadb_acquire_nomem", KSTAT_DATA_UINT64
);
90 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_sadb_acquire_toofull
,
91 "sadb_acquire_toofull", KSTAT_DATA_UINT64
);
92 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_sadb_acquire_timeout
,
93 "sadb_acquire_timeout", KSTAT_DATA_UINT64
);
95 /* SPD drop statistics. */
96 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_spd_ahesp_diffid
,
97 "spd_ahesp_diffid", KSTAT_DATA_UINT64
);
98 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_spd_loopback_mismatch
,
99 "spd_loopback_mismatch", KSTAT_DATA_UINT64
);
100 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_spd_explicit
,
101 "spd_explicit", KSTAT_DATA_UINT64
);
102 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_spd_got_secure
,
103 "spd_got_secure", KSTAT_DATA_UINT64
);
104 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_spd_got_clear
,
105 "spd_got_clear", KSTAT_DATA_UINT64
);
106 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_spd_bad_ahalg
,
107 "spd_bad_ahalg", KSTAT_DATA_UINT64
);
108 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_spd_got_ah
,
109 "spd_got_ah", KSTAT_DATA_UINT64
);
110 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_spd_bad_espealg
,
111 "spd_bad_espealg", KSTAT_DATA_UINT64
);
112 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_spd_bad_espaalg
,
113 "spd_bad_espaalg", KSTAT_DATA_UINT64
);
114 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_spd_got_esp
,
115 "spd_got_esp", KSTAT_DATA_UINT64
);
116 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_spd_got_selfencap
,
117 "spd_got_selfencap", KSTAT_DATA_UINT64
);
118 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_spd_bad_selfencap
,
119 "spd_bad_selfencap", KSTAT_DATA_UINT64
);
120 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_spd_nomem
,
121 "spd_nomem", KSTAT_DATA_UINT64
);
122 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_spd_ah_badid
,
123 "spd_ah_badid", KSTAT_DATA_UINT64
);
124 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_spd_ah_innermismatch
,
125 "spd_ah_innermismatch", KSTAT_DATA_UINT64
);
126 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_spd_esp_innermismatch
,
127 "spd_esp_innermismatch", KSTAT_DATA_UINT64
);
128 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_spd_esp_badid
,
129 "spd_esp_badid", KSTAT_DATA_UINT64
);
130 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_spd_no_policy
,
131 "spd_no_policy", KSTAT_DATA_UINT64
);
132 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_spd_malformed_packet
,
133 "spd_malformed_packet", KSTAT_DATA_UINT64
);
134 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_spd_malformed_frag
,
135 "spd_malformed_frag", KSTAT_DATA_UINT64
);
136 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_spd_overlap_frag
,
137 "spd_overlap_frag", KSTAT_DATA_UINT64
);
138 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_spd_evil_frag
,
139 "spd_evil_frag", KSTAT_DATA_UINT64
);
140 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_spd_max_frags
,
141 "spd_max_frags", KSTAT_DATA_UINT64
);
142 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_spd_expired_frags
,
143 "spd_expired_frags", KSTAT_DATA_UINT64
);
145 /* ESP-specific drop statistics. */
147 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_esp_nomem
,
148 "esp_nomem", KSTAT_DATA_UINT64
);
149 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_esp_no_sa
,
150 "esp_no_sa", KSTAT_DATA_UINT64
);
151 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_esp_early_replay
,
152 "esp_early_replay", KSTAT_DATA_UINT64
);
153 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_esp_replay
,
154 "esp_replay", KSTAT_DATA_UINT64
);
155 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_esp_bytes_expire
,
156 "esp_bytes_expire", KSTAT_DATA_UINT64
);
157 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_esp_bad_padlen
,
158 "esp_bad_padlen", KSTAT_DATA_UINT64
);
159 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_esp_bad_padding
,
160 "esp_bad_padding", KSTAT_DATA_UINT64
);
161 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_esp_bad_auth
,
162 "esp_bad_auth", KSTAT_DATA_UINT64
);
163 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_esp_crypto_failed
,
164 "esp_crypto_failed", KSTAT_DATA_UINT64
);
165 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_esp_icmp
,
166 "esp_icmp", KSTAT_DATA_UINT64
);
167 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_esp_nat_t_ipsec
,
168 "esp_nat_t_ipsec", KSTAT_DATA_UINT64
);
169 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_esp_nat_t_ka
,
170 "esp_nat_t_ka", KSTAT_DATA_UINT64
);
171 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_esp_iv_wrap
,
172 "esp_iv_wrap", KSTAT_DATA_UINT64
);
174 /* AH-specific drop statistics. */
175 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_ah_nomem
,
176 "ah_nomem", KSTAT_DATA_UINT64
);
177 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_ah_bad_v6_hdrs
,
178 "ah_bad_v6_hdrs", KSTAT_DATA_UINT64
);
179 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_ah_bad_v4_opts
,
180 "ah_bad_v4_opts", KSTAT_DATA_UINT64
);
181 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_ah_no_sa
,
182 "ah_no_sa", KSTAT_DATA_UINT64
);
183 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_ah_bad_length
,
184 "ah_bad_length", KSTAT_DATA_UINT64
);
185 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_ah_bad_auth
,
186 "ah_bad_auth", KSTAT_DATA_UINT64
);
187 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_ah_crypto_failed
,
188 "ah_crypto_failed", KSTAT_DATA_UINT64
);
189 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_ah_early_replay
,
190 "ah_early_replay", KSTAT_DATA_UINT64
);
191 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_ah_replay
,
192 "ah_replay", KSTAT_DATA_UINT64
);
193 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_ah_bytes_expire
,
194 "ah_bytes_expire", KSTAT_DATA_UINT64
);
196 /* IP-specific drop statistics. */
197 kstat_named_init(&ipss
->ipsec_ip_drop_types
->ipds_ip_ipsec_not_loaded
,
198 "ip_ipsec_not_loaded", KSTAT_DATA_UINT64
);
200 kstat_install(ipss
->ipsec_ip_drop_kstat
);
204 ip_drop_destroy(ipsec_stack_t
*ipss
)
206 kstat_delete_netstack(ipss
->ipsec_ip_drop_kstat
,
207 ipss
->ipsec_netstack
->netstack_stackid
);
208 ipss
->ipsec_ip_drop_kstat
= NULL
;
209 ipss
->ipsec_ip_drop_types
= NULL
;
213 * Register a packet dropper.
216 ip_drop_register(ipdropper_t
*ipd
, char *name
)
218 if (ipd
->ipd_name
!= NULL
) {
220 "ip_drop_register: ipdropper %s already registered with %s",
221 name
, ipd
->ipd_name
);
225 /* Assume that name is reasonable in length. This isn't user-land. */
226 ipd
->ipd_name
= kmem_alloc(strlen(name
) + 1, KM_SLEEP
);
227 (void) strcpy(ipd
->ipd_name
, name
);
231 * Un-register a packet dropper.
234 ip_drop_unregister(ipdropper_t
*ipd
)
236 if (ipd
->ipd_name
== NULL
) {
238 "ip_drop_unregister: not registered (%p)\n",
242 kmem_free(ipd
->ipd_name
, strlen(ipd
->ipd_name
) + 1);
244 ipd
->ipd_name
= NULL
;
248 * Actually drop a packet. Many things could happen here, but at the least,
249 * the packet will be freemsg()ed.
252 ip_drop_packet(mblk_t
*mp
, boolean_t inbound
, ill_t
*ill
,
253 struct kstat_named
*counter
, ipdropper_t
*who_called
)
259 * Return immediately - NULL packets should not affect any
265 ASSERT(mp
->b_datap
->db_type
== M_DATA
);
267 /* Increment the bean counter, if available. */
268 if (counter
!= NULL
) {
269 switch (counter
->data_type
) {
270 case KSTAT_DATA_INT32
:
271 counter
->value
.i32
++;
273 case KSTAT_DATA_UINT32
:
274 counter
->value
.ui32
++;
276 case KSTAT_DATA_INT64
:
277 counter
->value
.i64
++;
279 case KSTAT_DATA_UINT64
:
280 counter
->value
.ui64
++;
282 /* Other types we can't handle for now. */
288 else if (who_called
!= NULL
)
289 str
= who_called
->ipd_name
;
291 str
= "Unspecified IPsec drop";
294 ip_drop_input(str
, mp
, ill
);
296 ip_drop_output(str
, mp
, ill
);
298 /* TODO: queue the packet onto a snoop-friendly queue. */
301 * ASSERT this isn't a b_next linked mblk chain where a
302 * chained dropper should be used instead
304 ASSERT(mp
->b_prev
== NULL
&& mp
->b_next
== NULL
);
309 * This is just a convinient place for dtrace to see dropped packets
313 ip_drop_input(char *str
, mblk_t
*mp
, ill_t
*ill
)
318 if (IPH_HDR_VERSION(mp
->b_rptr
) == IPV4_VERSION
) {
319 ipha_t
*ipha
= (ipha_t
*)mp
->b_rptr
;
321 DTRACE_IP7(drop__in
, mblk_t
*, mp
, conn_t
*, NULL
, void_ip_t
*,
322 ipha
, __dtrace_ipsr_ill_t
*, ill
, ipha_t
*, ipha
,
323 ip6_t
*, NULL
, int, 0);
325 ip6_t
*ip6h
= (ip6_t
*)mp
->b_rptr
;
327 DTRACE_IP7(drop__in
, mblk_t
*, mp
, conn_t
*, NULL
, void_ip_t
*,
328 ip6h
, __dtrace_ipsr_ill_t
*, ill
, ipha_t
*, NULL
,
329 ip6_t
*, ip6h
, int, 0);
335 ip_drop_output(char *str
, mblk_t
*mp
, ill_t
*ill
)
340 if (IPH_HDR_VERSION(mp
->b_rptr
) == IPV4_VERSION
) {
341 ipha_t
*ipha
= (ipha_t
*)mp
->b_rptr
;
343 DTRACE_IP7(drop__out
, mblk_t
*, mp
, conn_t
*, NULL
, void_ip_t
*,
344 ipha
, __dtrace_ipsr_ill_t
*, ill
, ipha_t
*, ipha
,
345 ip6_t
*, NULL
, int, 0);
347 ip6_t
*ip6h
= (ip6_t
*)mp
->b_rptr
;
349 DTRACE_IP7(drop__out
, mblk_t
*, mp
, conn_t
*, NULL
, void_ip_t
*,
350 ip6h
, __dtrace_ipsr_ill_t
*, ill
, ipha_t
*, NULL
,
351 ip6_t
*, ip6h
, int, 0);