Print this page
7819 IPv6 Packet and MTU bug
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/inet/ip/ip6.c
+++ new/usr/src/uts/common/inet/ip/ip6.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 * Copyright (c) 1990 Mentat Inc.
24 + * Copyright 2017 OmniTI Computer Consulting, Inc. All rights reserved.
24 25 */
25 26
26 27 #include <sys/types.h>
27 28 #include <sys/stream.h>
28 29 #include <sys/dlpi.h>
29 30 #include <sys/stropts.h>
30 31 #include <sys/sysmacros.h>
31 32 #include <sys/strsun.h>
32 33 #include <sys/strlog.h>
33 34 #include <sys/strsubr.h>
34 35 #define _SUN_TPI_VERSION 2
35 36 #include <sys/tihdr.h>
36 37 #include <sys/ddi.h>
37 38 #include <sys/sunddi.h>
38 39 #include <sys/cmn_err.h>
39 40 #include <sys/debug.h>
40 41 #include <sys/sdt.h>
41 42 #include <sys/kobj.h>
42 43 #include <sys/zone.h>
43 44 #include <sys/neti.h>
44 45 #include <sys/hook.h>
45 46
46 47 #include <sys/kmem.h>
47 48 #include <sys/systm.h>
48 49 #include <sys/param.h>
49 50 #include <sys/socket.h>
50 51 #include <sys/vtrace.h>
51 52 #include <sys/isa_defs.h>
52 53 #include <sys/atomic.h>
53 54 #include <sys/policy.h>
54 55 #include <sys/mac.h>
55 56 #include <net/if.h>
56 57 #include <net/if_types.h>
57 58 #include <net/route.h>
58 59 #include <net/if_dl.h>
59 60 #include <sys/sockio.h>
60 61 #include <netinet/in.h>
61 62 #include <netinet/ip6.h>
62 63 #include <netinet/icmp6.h>
63 64 #include <netinet/sctp.h>
64 65
65 66 #include <inet/common.h>
66 67 #include <inet/mi.h>
67 68 #include <inet/optcom.h>
68 69 #include <inet/mib2.h>
69 70 #include <inet/nd.h>
70 71 #include <inet/arp.h>
71 72
72 73 #include <inet/ip.h>
73 74 #include <inet/ip_impl.h>
74 75 #include <inet/ip6.h>
75 76 #include <inet/ip6_asp.h>
76 77 #include <inet/tcp.h>
77 78 #include <inet/tcp_impl.h>
78 79 #include <inet/udp_impl.h>
79 80 #include <inet/ipp_common.h>
80 81
81 82 #include <inet/ip_multi.h>
82 83 #include <inet/ip_if.h>
83 84 #include <inet/ip_ire.h>
84 85 #include <inet/ip_rts.h>
85 86 #include <inet/ip_ndp.h>
86 87 #include <net/pfkeyv2.h>
87 88 #include <inet/sadb.h>
88 89 #include <inet/ipsec_impl.h>
89 90 #include <inet/iptun/iptun_impl.h>
90 91 #include <inet/sctp_ip.h>
91 92 #include <sys/pattr.h>
92 93 #include <inet/ipclassifier.h>
93 94 #include <inet/ipsecah.h>
94 95 #include <inet/rawip_impl.h>
95 96 #include <inet/rts_impl.h>
96 97 #include <sys/squeue_impl.h>
97 98 #include <sys/squeue.h>
98 99
99 100 #include <sys/tsol/label.h>
100 101 #include <sys/tsol/tnet.h>
101 102
102 103 /* Temporary; for CR 6451644 work-around */
103 104 #include <sys/ethernet.h>
104 105
105 106 /*
106 107 * Naming conventions:
107 108 * These rules should be judiciously applied
108 109 * if there is a need to identify something as IPv6 versus IPv4
109 110 * IPv6 funcions will end with _v6 in the ip module.
110 111 * IPv6 funcions will end with _ipv6 in the transport modules.
111 112 * IPv6 macros:
112 113 * Some macros end with _V6; e.g. ILL_FRAG_HASH_V6
113 114 * Some macros start with V6_; e.g. V6_OR_V4_INADDR_ANY
114 115 * And then there are ..V4_PART_OF_V6.
115 116 * The intent is that macros in the ip module end with _V6.
116 117 * IPv6 global variables will start with ipv6_
117 118 * IPv6 structures will start with ipv6
118 119 * IPv6 defined constants should start with IPV6_
119 120 * (but then there are NDP_DEFAULT_VERS_PRI_AND_FLOW, etc)
120 121 */
121 122
122 123 /*
123 124 * ip6opt_ls is used to enable IPv6 (via /etc/system on TX systems).
124 125 * We need to do this because we didn't obtain the IP6OPT_LS (0x0a)
125 126 * from IANA. This mechanism will remain in effect until an official
126 127 * number is obtained.
127 128 */
128 129 uchar_t ip6opt_ls;
129 130
130 131 const in6_addr_t ipv6_all_ones =
131 132 { 0xffffffffU, 0xffffffffU, 0xffffffffU, 0xffffffffU };
132 133 const in6_addr_t ipv6_all_zeros = { 0, 0, 0, 0 };
133 134
134 135 #ifdef _BIG_ENDIAN
135 136 const in6_addr_t ipv6_unspecified_group = { 0xff000000U, 0, 0, 0 };
136 137 #else /* _BIG_ENDIAN */
137 138 const in6_addr_t ipv6_unspecified_group = { 0x000000ffU, 0, 0, 0 };
138 139 #endif /* _BIG_ENDIAN */
139 140
140 141 #ifdef _BIG_ENDIAN
141 142 const in6_addr_t ipv6_loopback = { 0, 0, 0, 0x00000001U };
142 143 #else /* _BIG_ENDIAN */
143 144 const in6_addr_t ipv6_loopback = { 0, 0, 0, 0x01000000U };
144 145 #endif /* _BIG_ENDIAN */
145 146
146 147 #ifdef _BIG_ENDIAN
147 148 const in6_addr_t ipv6_all_hosts_mcast = { 0xff020000U, 0, 0, 0x00000001U };
148 149 #else /* _BIG_ENDIAN */
149 150 const in6_addr_t ipv6_all_hosts_mcast = { 0x000002ffU, 0, 0, 0x01000000U };
150 151 #endif /* _BIG_ENDIAN */
151 152
152 153 #ifdef _BIG_ENDIAN
153 154 const in6_addr_t ipv6_all_rtrs_mcast = { 0xff020000U, 0, 0, 0x00000002U };
154 155 #else /* _BIG_ENDIAN */
155 156 const in6_addr_t ipv6_all_rtrs_mcast = { 0x000002ffU, 0, 0, 0x02000000U };
156 157 #endif /* _BIG_ENDIAN */
157 158
158 159 #ifdef _BIG_ENDIAN
159 160 const in6_addr_t ipv6_all_v2rtrs_mcast = { 0xff020000U, 0, 0, 0x00000016U };
160 161 #else /* _BIG_ENDIAN */
161 162 const in6_addr_t ipv6_all_v2rtrs_mcast = { 0x000002ffU, 0, 0, 0x16000000U };
162 163 #endif /* _BIG_ENDIAN */
163 164
164 165 #ifdef _BIG_ENDIAN
165 166 const in6_addr_t ipv6_solicited_node_mcast =
166 167 { 0xff020000U, 0, 0x00000001U, 0xff000000U };
167 168 #else /* _BIG_ENDIAN */
168 169 const in6_addr_t ipv6_solicited_node_mcast =
169 170 { 0x000002ffU, 0, 0x01000000U, 0x000000ffU };
170 171 #endif /* _BIG_ENDIAN */
171 172
172 173 static boolean_t icmp_inbound_verify_v6(mblk_t *, icmp6_t *, ip_recv_attr_t *);
173 174 static void icmp_inbound_too_big_v6(icmp6_t *, ip_recv_attr_t *);
174 175 static void icmp_pkt_v6(mblk_t *, void *, size_t, const in6_addr_t *,
175 176 ip_recv_attr_t *);
176 177 static void icmp_redirect_v6(mblk_t *, ip6_t *, nd_redirect_t *,
177 178 ip_recv_attr_t *);
178 179 static void icmp_send_redirect_v6(mblk_t *, in6_addr_t *,
179 180 in6_addr_t *, ip_recv_attr_t *);
180 181 static void icmp_send_reply_v6(mblk_t *, ip6_t *, icmp6_t *,
181 182 ip_recv_attr_t *);
182 183 static boolean_t ip_source_routed_v6(ip6_t *, mblk_t *, ip_stack_t *);
183 184
184 185 /*
185 186 * icmp_inbound_v6 deals with ICMP messages that are handled by IP.
186 187 * If the ICMP message is consumed by IP, i.e., it should not be delivered
187 188 * to any IPPROTO_ICMP raw sockets, then it returns NULL.
188 189 * Likewise, if the ICMP error is misformed (too short, etc), then it
189 190 * returns NULL. The caller uses this to determine whether or not to send
190 191 * to raw sockets.
191 192 *
192 193 * All error messages are passed to the matching transport stream.
193 194 *
194 195 * See comment for icmp_inbound_v4() on how IPsec is handled.
195 196 */
196 197 mblk_t *
197 198 icmp_inbound_v6(mblk_t *mp, ip_recv_attr_t *ira)
198 199 {
199 200 icmp6_t *icmp6;
200 201 ip6_t *ip6h; /* Outer header */
201 202 int ip_hdr_length; /* Outer header length */
202 203 boolean_t interested;
203 204 ill_t *ill = ira->ira_ill;
204 205 ip_stack_t *ipst = ill->ill_ipst;
205 206 mblk_t *mp_ret = NULL;
206 207
207 208 ip6h = (ip6_t *)mp->b_rptr;
208 209
209 210 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInMsgs);
210 211
211 212 /* Check for Martian packets */
212 213 if (IN6_IS_ADDR_MULTICAST(&ip6h->ip6_src)) {
213 214 BUMP_MIB(ill->ill_ip_mib, ipIfStatsInAddrErrors);
214 215 ip_drop_input("ipIfStatsInAddrErrors: mcast src", mp, ill);
215 216 freemsg(mp);
216 217 return (NULL);
217 218 }
218 219
219 220 /* Make sure ira_l2src is set for ndp_input */
220 221 if (!(ira->ira_flags & IRAF_L2SRC_SET))
221 222 ip_setl2src(mp, ira, ira->ira_rill);
222 223
223 224 ip_hdr_length = ira->ira_ip_hdr_length;
224 225 if ((mp->b_wptr - mp->b_rptr) < (ip_hdr_length + ICMP6_MINLEN)) {
225 226 if (ira->ira_pktlen < (ip_hdr_length + ICMP6_MINLEN)) {
226 227 BUMP_MIB(ill->ill_ip_mib, ipIfStatsInTruncatedPkts);
227 228 ip_drop_input("ipIfStatsInTruncatedPkts", mp, ill);
228 229 freemsg(mp);
229 230 return (NULL);
230 231 }
231 232 ip6h = ip_pullup(mp, ip_hdr_length + ICMP6_MINLEN, ira);
232 233 if (ip6h == NULL) {
233 234 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInErrors);
234 235 freemsg(mp);
235 236 return (NULL);
236 237 }
237 238 }
238 239
239 240 icmp6 = (icmp6_t *)(&mp->b_rptr[ip_hdr_length]);
240 241 DTRACE_PROBE2(icmp__inbound__v6, ip6_t *, ip6h, icmp6_t *, icmp6);
241 242 ip2dbg(("icmp_inbound_v6: type %d code %d\n", icmp6->icmp6_type,
242 243 icmp6->icmp6_code));
243 244
244 245 /*
245 246 * We will set "interested" to "true" if we should pass a copy to
246 247 * the transport i.e., if it is an error message.
247 248 */
248 249 interested = !(icmp6->icmp6_type & ICMP6_INFOMSG_MASK);
249 250
250 251 switch (icmp6->icmp6_type) {
251 252 case ICMP6_DST_UNREACH:
252 253 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInDestUnreachs);
253 254 if (icmp6->icmp6_code == ICMP6_DST_UNREACH_ADMIN)
254 255 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInAdminProhibs);
255 256 break;
256 257
257 258 case ICMP6_TIME_EXCEEDED:
258 259 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInTimeExcds);
259 260 break;
260 261
261 262 case ICMP6_PARAM_PROB:
262 263 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInParmProblems);
263 264 break;
264 265
265 266 case ICMP6_PACKET_TOO_BIG:
266 267 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInPktTooBigs);
267 268 break;
268 269
269 270 case ICMP6_ECHO_REQUEST:
270 271 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInEchos);
271 272 if (IN6_IS_ADDR_MULTICAST(&ip6h->ip6_dst) &&
272 273 !ipst->ips_ipv6_resp_echo_mcast)
273 274 break;
274 275
275 276 /*
276 277 * We must have exclusive use of the mblk to convert it to
277 278 * a response.
278 279 * If not, we copy it.
279 280 */
280 281 if (mp->b_datap->db_ref > 1) {
281 282 mblk_t *mp1;
282 283
283 284 mp1 = copymsg(mp);
284 285 if (mp1 == NULL) {
285 286 BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards);
286 287 ip_drop_input("ipIfStatsInDiscards - copymsg",
287 288 mp, ill);
288 289 freemsg(mp);
289 290 return (NULL);
290 291 }
291 292 freemsg(mp);
292 293 mp = mp1;
293 294 ip6h = (ip6_t *)mp->b_rptr;
294 295 icmp6 = (icmp6_t *)(&mp->b_rptr[ip_hdr_length]);
295 296 }
296 297
297 298 icmp6->icmp6_type = ICMP6_ECHO_REPLY;
298 299 icmp_send_reply_v6(mp, ip6h, icmp6, ira);
299 300 return (NULL);
300 301
301 302 case ICMP6_ECHO_REPLY:
302 303 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInEchoReplies);
303 304 break;
304 305
305 306 case ND_ROUTER_SOLICIT:
306 307 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInRouterSolicits);
307 308 break;
308 309
309 310 case ND_ROUTER_ADVERT:
310 311 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInRouterAdvertisements);
311 312 break;
312 313
313 314 case ND_NEIGHBOR_SOLICIT:
314 315 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInNeighborSolicits);
315 316 ndp_input(mp, ira);
316 317 return (NULL);
317 318
318 319 case ND_NEIGHBOR_ADVERT:
319 320 BUMP_MIB(ill->ill_icmp6_mib,
320 321 ipv6IfIcmpInNeighborAdvertisements);
321 322 ndp_input(mp, ira);
322 323 return (NULL);
323 324
324 325 case ND_REDIRECT:
325 326 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInRedirects);
326 327
327 328 if (ipst->ips_ipv6_ignore_redirect)
328 329 break;
329 330
330 331 /* We now allow a RAW socket to receive this. */
331 332 interested = B_TRUE;
332 333 break;
333 334
334 335 /*
335 336 * The next three icmp messages will be handled by MLD.
336 337 * Pass all valid MLD packets up to any process(es)
337 338 * listening on a raw ICMP socket.
338 339 */
339 340 case MLD_LISTENER_QUERY:
340 341 case MLD_LISTENER_REPORT:
341 342 case MLD_LISTENER_REDUCTION:
342 343 mp = mld_input(mp, ira);
343 344 return (mp);
344 345 default:
345 346 break;
346 347 }
347 348 /*
348 349 * See if there is an ICMP client to avoid an extra copymsg/freemsg
349 350 * if there isn't one.
350 351 */
351 352 if (ipst->ips_ipcl_proto_fanout_v6[IPPROTO_ICMPV6].connf_head != NULL) {
352 353 /* If there is an ICMP client and we want one too, copy it. */
353 354
354 355 if (!interested) {
355 356 /* Caller will deliver to RAW sockets */
356 357 return (mp);
357 358 }
358 359 mp_ret = copymsg(mp);
359 360 if (mp_ret == NULL) {
360 361 BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards);
361 362 ip_drop_input("ipIfStatsInDiscards - copymsg", mp, ill);
362 363 }
363 364 } else if (!interested) {
364 365 /* Neither we nor raw sockets are interested. Drop packet now */
365 366 freemsg(mp);
366 367 return (NULL);
367 368 }
368 369
369 370 /*
370 371 * ICMP error or redirect packet. Make sure we have enough of
371 372 * the header and that db_ref == 1 since we might end up modifying
372 373 * the packet.
373 374 */
374 375 if (mp->b_cont != NULL) {
375 376 if (ip_pullup(mp, -1, ira) == NULL) {
376 377 BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards);
377 378 ip_drop_input("ipIfStatsInDiscards - ip_pullup",
378 379 mp, ill);
379 380 freemsg(mp);
380 381 return (mp_ret);
381 382 }
382 383 }
383 384
384 385 if (mp->b_datap->db_ref > 1) {
385 386 mblk_t *mp1;
386 387
387 388 mp1 = copymsg(mp);
388 389 if (mp1 == NULL) {
389 390 BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards);
390 391 ip_drop_input("ipIfStatsInDiscards - copymsg", mp, ill);
391 392 freemsg(mp);
392 393 return (mp_ret);
393 394 }
394 395 freemsg(mp);
395 396 mp = mp1;
396 397 }
397 398
398 399 /*
399 400 * In case mp has changed, verify the message before any further
400 401 * processes.
401 402 */
402 403 ip6h = (ip6_t *)mp->b_rptr;
403 404 icmp6 = (icmp6_t *)(&mp->b_rptr[ip_hdr_length]);
404 405 if (!icmp_inbound_verify_v6(mp, icmp6, ira)) {
405 406 freemsg(mp);
406 407 return (mp_ret);
407 408 }
408 409
409 410 switch (icmp6->icmp6_type) {
410 411 case ND_REDIRECT:
411 412 icmp_redirect_v6(mp, ip6h, (nd_redirect_t *)icmp6, ira);
412 413 break;
413 414 case ICMP6_PACKET_TOO_BIG:
414 415 /* Update DCE and adjust MTU is icmp header if needed */
415 416 icmp_inbound_too_big_v6(icmp6, ira);
416 417 /* FALLTHRU */
417 418 default:
418 419 icmp_inbound_error_fanout_v6(mp, icmp6, ira);
419 420 break;
420 421 }
421 422
422 423 return (mp_ret);
423 424 }
424 425
425 426 /*
426 427 * Send an ICMP echo reply.
427 428 * The caller has already updated the payload part of the packet.
428 429 * We handle the ICMP checksum, IP source address selection and feed
429 430 * the packet into ip_output_simple.
430 431 */
431 432 static void
432 433 icmp_send_reply_v6(mblk_t *mp, ip6_t *ip6h, icmp6_t *icmp6,
433 434 ip_recv_attr_t *ira)
434 435 {
435 436 uint_t ip_hdr_length = ira->ira_ip_hdr_length;
436 437 ill_t *ill = ira->ira_ill;
437 438 ip_stack_t *ipst = ill->ill_ipst;
438 439 ip_xmit_attr_t ixas;
439 440 in6_addr_t origsrc;
440 441
441 442 /*
442 443 * Remove any extension headers (do not reverse a source route)
443 444 * and clear the flow id (keep traffic class for now).
444 445 */
445 446 if (ip_hdr_length != IPV6_HDR_LEN) {
446 447 int i;
447 448
448 449 for (i = 0; i < IPV6_HDR_LEN; i++) {
449 450 mp->b_rptr[ip_hdr_length - i - 1] =
450 451 mp->b_rptr[IPV6_HDR_LEN - i - 1];
451 452 }
452 453 mp->b_rptr += (ip_hdr_length - IPV6_HDR_LEN);
453 454 ip6h = (ip6_t *)mp->b_rptr;
454 455 ip6h->ip6_nxt = IPPROTO_ICMPV6;
455 456 i = ntohs(ip6h->ip6_plen);
456 457 i -= (ip_hdr_length - IPV6_HDR_LEN);
457 458 ip6h->ip6_plen = htons(i);
458 459 ip_hdr_length = IPV6_HDR_LEN;
459 460 ASSERT(ntohs(ip6h->ip6_plen) + IPV6_HDR_LEN == msgdsize(mp));
460 461 }
461 462 ip6h->ip6_vcf &= ~IPV6_FLOWINFO_FLOWLABEL;
462 463
463 464 /* Reverse the source and destination addresses. */
464 465 origsrc = ip6h->ip6_src;
465 466 ip6h->ip6_src = ip6h->ip6_dst;
466 467 ip6h->ip6_dst = origsrc;
467 468
468 469 /* set the hop limit */
469 470 ip6h->ip6_hops = ipst->ips_ipv6_def_hops;
470 471
471 472 /*
472 473 * Prepare for checksum by putting icmp length in the icmp
473 474 * checksum field. The checksum is calculated in ip_output
474 475 */
475 476 icmp6->icmp6_cksum = ip6h->ip6_plen;
476 477
477 478 bzero(&ixas, sizeof (ixas));
478 479 ixas.ixa_flags = IXAF_BASIC_SIMPLE_V6;
479 480 ixas.ixa_zoneid = ira->ira_zoneid;
480 481 ixas.ixa_cred = kcred;
481 482 ixas.ixa_cpid = NOPID;
482 483 ixas.ixa_tsl = ira->ira_tsl; /* Behave as a multi-level responder */
483 484 ixas.ixa_ifindex = 0;
484 485 ixas.ixa_ipst = ipst;
485 486 ixas.ixa_multicast_ttl = IP_DEFAULT_MULTICAST_TTL;
486 487
487 488 if (!(ira->ira_flags & IRAF_IPSEC_SECURE)) {
488 489 /*
489 490 * This packet should go out the same way as it
490 491 * came in i.e in clear, independent of the IPsec
491 492 * policy for transmitting packets.
492 493 */
493 494 ixas.ixa_flags |= IXAF_NO_IPSEC;
494 495 } else {
495 496 if (!ipsec_in_to_out(ira, &ixas, mp, NULL, ip6h)) {
496 497 BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards);
497 498 /* Note: mp already consumed and ip_drop_packet done */
498 499 return;
499 500 }
500 501 }
501 502
502 503 /* Was the destination (now source) link-local? Send out same group */
503 504 if (IN6_IS_ADDR_LINKSCOPE(&ip6h->ip6_src)) {
504 505 ixas.ixa_flags |= IXAF_SCOPEID_SET;
505 506 if (IS_UNDER_IPMP(ill))
506 507 ixas.ixa_scopeid = ill_get_upper_ifindex(ill);
507 508 else
508 509 ixas.ixa_scopeid = ill->ill_phyint->phyint_ifindex;
509 510 }
510 511
511 512 if (ira->ira_flags & IRAF_MULTIBROADCAST) {
512 513 /*
513 514 * Not one or our addresses (IRE_LOCALs), thus we let
514 515 * ip_output_simple pick the source.
515 516 */
516 517 ip6h->ip6_src = ipv6_all_zeros;
517 518 ixas.ixa_flags |= IXAF_SET_SOURCE;
518 519 }
519 520
520 521 /* Should we send using dce_pmtu? */
521 522 if (ipst->ips_ipv6_icmp_return_pmtu)
522 523 ixas.ixa_flags |= IXAF_PMTU_DISCOVERY;
523 524
524 525 (void) ip_output_simple(mp, &ixas);
525 526 ixa_cleanup(&ixas);
526 527
527 528 }
528 529
529 530 /*
530 531 * Verify the ICMP messages for either for ICMP error or redirect packet.
531 532 * The caller should have fully pulled up the message. If it's a redirect
532 533 * packet, only basic checks on IP header will be done; otherwise, verify
533 534 * the packet by looking at the included ULP header.
534 535 *
535 536 * Called before icmp_inbound_error_fanout_v6 is called.
536 537 */
537 538 static boolean_t
538 539 icmp_inbound_verify_v6(mblk_t *mp, icmp6_t *icmp6, ip_recv_attr_t *ira)
539 540 {
540 541 ill_t *ill = ira->ira_ill;
541 542 uint16_t hdr_length;
542 543 uint8_t *nexthdrp;
543 544 uint8_t nexthdr;
544 545 ip_stack_t *ipst = ill->ill_ipst;
545 546 conn_t *connp;
546 547 ip6_t *ip6h; /* Inner header */
547 548
548 549 ip6h = (ip6_t *)&icmp6[1];
549 550 if ((uchar_t *)ip6h + IPV6_HDR_LEN > mp->b_wptr)
550 551 goto truncated;
551 552
552 553 if (icmp6->icmp6_type == ND_REDIRECT) {
553 554 hdr_length = sizeof (nd_redirect_t);
554 555 } else {
555 556 if ((IPH_HDR_VERSION(ip6h) != IPV6_VERSION))
556 557 goto discard_pkt;
557 558 hdr_length = IPV6_HDR_LEN;
558 559 }
559 560
560 561 if ((uchar_t *)ip6h + hdr_length > mp->b_wptr)
561 562 goto truncated;
562 563
563 564 /*
564 565 * Stop here for ICMP_REDIRECT.
565 566 */
566 567 if (icmp6->icmp6_type == ND_REDIRECT)
567 568 return (B_TRUE);
568 569
569 570 /*
570 571 * ICMP errors only.
571 572 */
572 573 if (!ip_hdr_length_nexthdr_v6(mp, ip6h, &hdr_length, &nexthdrp))
573 574 goto discard_pkt;
574 575 nexthdr = *nexthdrp;
575 576
576 577 /* Try to pass the ICMP message to clients who need it */
577 578 switch (nexthdr) {
578 579 case IPPROTO_UDP:
579 580 /*
580 581 * Verify we have at least ICMP_MIN_TP_HDR_LEN bytes of
581 582 * transport header.
582 583 */
583 584 if ((uchar_t *)ip6h + hdr_length + ICMP_MIN_TP_HDR_LEN >
584 585 mp->b_wptr)
585 586 goto truncated;
586 587 break;
587 588 case IPPROTO_TCP: {
588 589 tcpha_t *tcpha;
589 590
590 591 /*
591 592 * Verify we have at least ICMP_MIN_TP_HDR_LEN bytes of
592 593 * transport header.
593 594 */
594 595 if ((uchar_t *)ip6h + hdr_length + ICMP_MIN_TP_HDR_LEN >
595 596 mp->b_wptr)
596 597 goto truncated;
597 598
598 599 tcpha = (tcpha_t *)((uchar_t *)ip6h + hdr_length);
599 600 /*
600 601 * With IPMP we need to match across group, which we do
601 602 * since we have the upper ill from ira_ill.
602 603 */
603 604 connp = ipcl_tcp_lookup_reversed_ipv6(ip6h, tcpha, TCPS_LISTEN,
604 605 ill->ill_phyint->phyint_ifindex, ipst);
605 606 if (connp == NULL)
606 607 goto discard_pkt;
607 608
608 609 if ((connp->conn_verifyicmp != NULL) &&
609 610 !connp->conn_verifyicmp(connp, tcpha, NULL, icmp6, ira)) {
610 611 CONN_DEC_REF(connp);
611 612 goto discard_pkt;
612 613 }
613 614 CONN_DEC_REF(connp);
614 615 break;
615 616 }
616 617 case IPPROTO_SCTP:
617 618 /*
618 619 * Verify we have at least ICMP_MIN_TP_HDR_LEN bytes of
619 620 * transport header.
620 621 */
621 622 if ((uchar_t *)ip6h + hdr_length + ICMP_MIN_TP_HDR_LEN >
622 623 mp->b_wptr)
623 624 goto truncated;
624 625 break;
625 626 case IPPROTO_ESP:
626 627 case IPPROTO_AH:
627 628 break;
628 629 case IPPROTO_ENCAP:
629 630 case IPPROTO_IPV6: {
630 631 /* Look for self-encapsulated packets that caused an error */
631 632 ip6_t *in_ip6h;
632 633
633 634 in_ip6h = (ip6_t *)((uint8_t *)ip6h + hdr_length);
634 635 if ((uint8_t *)in_ip6h + (nexthdr == IPPROTO_ENCAP ?
635 636 sizeof (ipha_t) : sizeof (ip6_t)) > mp->b_wptr)
636 637 goto truncated;
637 638 break;
638 639 }
639 640 default:
640 641 break;
641 642 }
642 643
643 644 return (B_TRUE);
644 645
645 646 discard_pkt:
646 647 /* Bogus ICMP error. */
647 648 BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards);
648 649 return (B_FALSE);
649 650
650 651 truncated:
651 652 /* We pulled up everthing already. Must be truncated */
652 653 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInErrors);
653 654 return (B_FALSE);
654 655 }
655 656
656 657 /*
657 658 * Process received IPv6 ICMP Packet too big.
658 659 * The caller is responsible for validating the packet before passing it in
659 660 * and also to fanout the ICMP error to any matching transport conns. Assumes
660 661 * the message has been fully pulled up.
661 662 *
662 663 * Before getting here, the caller has called icmp_inbound_verify_v6()
663 664 * that should have verified with ULP to prevent undoing the changes we're
664 665 * going to make to DCE. For example, TCP might have verified that the packet
665 666 * which generated error is in the send window.
666 667 *
667 668 * In some cases modified this MTU in the ICMP header packet; the caller
668 669 * should pass to the matching ULP after this returns.
669 670 */
670 671 static void
671 672 icmp_inbound_too_big_v6(icmp6_t *icmp6, ip_recv_attr_t *ira)
672 673 {
673 674 uint32_t mtu;
674 675 dce_t *dce;
|
↓ open down ↓ |
641 lines elided |
↑ open up ↑ |
675 676 ill_t *ill = ira->ira_ill; /* Upper ill if IPMP */
676 677 ip_stack_t *ipst = ill->ill_ipst;
677 678 int old_max_frag;
678 679 in6_addr_t final_dst;
679 680 ip6_t *ip6h; /* Inner IP header */
680 681
681 682 /* Caller has already pulled up everything. */
682 683 ip6h = (ip6_t *)&icmp6[1];
683 684 final_dst = ip_get_dst_v6(ip6h, NULL, NULL);
684 685
686 + mtu = ntohl(icmp6->icmp6_mtu);
687 + if (mtu < IPV6_MIN_MTU) {
688 + /*
689 + * RFC 8021 suggests to ignore messages where mtu is
690 + * less than the IPv6 minimum.
691 + */
692 + ip1dbg(("Received mtu less than IPv6 "
693 + "min mtu %d: %d\n", IPV6_MIN_MTU, mtu));
694 + DTRACE_PROBE1(icmp6__too__small__mtu, uint32_t, mtu);
695 + return;
696 + }
697 +
685 698 /*
686 699 * For link local destinations matching simply on address is not
687 700 * sufficient. Same link local addresses for different ILL's is
688 701 * possible.
689 702 */
690 703 if (IN6_IS_ADDR_LINKSCOPE(&final_dst)) {
691 704 dce = dce_lookup_and_add_v6(&final_dst,
692 705 ill->ill_phyint->phyint_ifindex, ipst);
693 706 } else {
694 707 dce = dce_lookup_and_add_v6(&final_dst, 0, ipst);
695 708 }
696 709 if (dce == NULL) {
|
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
697 710 /* Couldn't add a unique one - ENOMEM */
698 711 if (ip_debug > 2) {
699 712 /* ip1dbg */
700 713 pr_addr_dbg("icmp_inbound_too_big_v6:"
701 714 "no dce for dst %s\n", AF_INET6,
702 715 &final_dst);
703 716 }
704 717 return;
705 718 }
706 719
707 - mtu = ntohl(icmp6->icmp6_mtu);
708 -
709 720 mutex_enter(&dce->dce_lock);
710 721 if (dce->dce_flags & DCEF_PMTU)
711 722 old_max_frag = dce->dce_pmtu;
712 723 else if (IN6_IS_ADDR_MULTICAST(&final_dst))
713 724 old_max_frag = ill->ill_mc_mtu;
714 725 else
715 726 old_max_frag = ill->ill_mtu;
716 727
717 - if (mtu < IPV6_MIN_MTU) {
718 - ip1dbg(("Received mtu less than IPv6 "
719 - "min mtu %d: %d\n", IPV6_MIN_MTU, mtu));
720 - mtu = IPV6_MIN_MTU;
721 - /*
722 - * If an mtu less than IPv6 min mtu is received,
723 - * we must include a fragment header in
724 - * subsequent packets.
725 - */
726 - dce->dce_flags |= DCEF_TOO_SMALL_PMTU;
727 - } else {
728 - dce->dce_flags &= ~DCEF_TOO_SMALL_PMTU;
729 - }
730 728 ip1dbg(("Received mtu from router: %d\n", mtu));
729 + DTRACE_PROBE1(icmp6__received__mtu, uint32_t, mtu);
731 730 dce->dce_pmtu = MIN(old_max_frag, mtu);
731 + icmp6->icmp6_mtu = htonl(dce->dce_pmtu);
732 732
733 - /* Prepare to send the new max frag size for the ULP. */
734 - if (dce->dce_flags & DCEF_TOO_SMALL_PMTU) {
735 - /*
736 - * If we need a fragment header in every packet
737 - * (above case or multirouting), make sure the
738 - * ULP takes it into account when computing the
739 - * payload size.
740 - */
741 - icmp6->icmp6_mtu = htonl(dce->dce_pmtu - sizeof (ip6_frag_t));
742 - } else {
743 - icmp6->icmp6_mtu = htonl(dce->dce_pmtu);
744 - }
745 733 /* We now have a PMTU for sure */
746 734 dce->dce_flags |= DCEF_PMTU;
747 735 dce->dce_last_change_time = TICK_TO_SEC(ddi_get_lbolt64());
736 +
748 737 mutex_exit(&dce->dce_lock);
749 738 /*
750 739 * After dropping the lock the new value is visible to everyone.
751 740 * Then we bump the generation number so any cached values reinspect
752 741 * the dce_t.
753 742 */
754 743 dce_increment_generation(dce);
755 744 dce_refrele(dce);
756 745 }
757 746
758 747 /*
759 748 * Fanout received ICMPv6 error packets to the transports.
760 749 * Assumes the IPv6 plus ICMPv6 headers have been pulled up but nothing else.
761 750 *
762 751 * The caller must have called icmp_inbound_verify_v6.
763 752 */
764 753 void
765 754 icmp_inbound_error_fanout_v6(mblk_t *mp, icmp6_t *icmp6, ip_recv_attr_t *ira)
766 755 {
767 756 uint16_t *up; /* Pointer to ports in ULP header */
768 757 uint32_t ports; /* reversed ports for fanout */
769 758 ip6_t rip6h; /* With reversed addresses */
770 759 ip6_t *ip6h; /* Inner IP header */
771 760 uint16_t hdr_length; /* Inner IP header length */
772 761 uint8_t *nexthdrp;
773 762 uint8_t nexthdr;
774 763 tcpha_t *tcpha;
775 764 conn_t *connp;
776 765 ill_t *ill = ira->ira_ill; /* Upper in the case of IPMP */
777 766 ip_stack_t *ipst = ill->ill_ipst;
778 767 ipsec_stack_t *ipss = ipst->ips_netstack->netstack_ipsec;
779 768
780 769 /* Caller has already pulled up everything. */
781 770 ip6h = (ip6_t *)&icmp6[1];
782 771 ASSERT(mp->b_cont == NULL);
783 772 ASSERT((uchar_t *)&ip6h[1] <= mp->b_wptr);
784 773
785 774 if (!ip_hdr_length_nexthdr_v6(mp, ip6h, &hdr_length, &nexthdrp))
786 775 goto drop_pkt;
787 776 nexthdr = *nexthdrp;
788 777 ira->ira_protocol = nexthdr;
789 778
790 779 /*
791 780 * We need a separate IP header with the source and destination
792 781 * addresses reversed to do fanout/classification because the ip6h in
793 782 * the ICMPv6 error is in the form we sent it out.
794 783 */
795 784 rip6h.ip6_src = ip6h->ip6_dst;
796 785 rip6h.ip6_dst = ip6h->ip6_src;
797 786 rip6h.ip6_nxt = nexthdr;
798 787
799 788 /* Try to pass the ICMP message to clients who need it */
800 789 switch (nexthdr) {
801 790 case IPPROTO_UDP: {
802 791 /* Attempt to find a client stream based on port. */
803 792 up = (uint16_t *)((uchar_t *)ip6h + hdr_length);
804 793
805 794 /* Note that we send error to all matches. */
806 795 ira->ira_flags |= IRAF_ICMP_ERROR;
807 796 ip_fanout_udp_multi_v6(mp, &rip6h, up[0], up[1], ira);
808 797 ira->ira_flags &= ~IRAF_ICMP_ERROR;
809 798 return;
810 799 }
811 800 case IPPROTO_TCP: {
812 801 /*
813 802 * Attempt to find a client stream based on port.
814 803 * Note that we do a reverse lookup since the header is
815 804 * in the form we sent it out.
816 805 */
817 806 tcpha = (tcpha_t *)((uchar_t *)ip6h + hdr_length);
818 807 /*
819 808 * With IPMP we need to match across group, which we do
820 809 * since we have the upper ill from ira_ill.
821 810 */
822 811 connp = ipcl_tcp_lookup_reversed_ipv6(ip6h, tcpha,
823 812 TCPS_LISTEN, ill->ill_phyint->phyint_ifindex, ipst);
824 813 if (connp == NULL) {
825 814 goto drop_pkt;
826 815 }
827 816
828 817 if (CONN_INBOUND_POLICY_PRESENT_V6(connp, ipss) ||
829 818 (ira->ira_flags & IRAF_IPSEC_SECURE)) {
830 819 mp = ipsec_check_inbound_policy(mp, connp,
831 820 NULL, ip6h, ira);
832 821 if (mp == NULL) {
833 822 BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards);
834 823 /* Note that mp is NULL */
835 824 ip_drop_input("ipIfStatsInDiscards", mp, ill);
836 825 CONN_DEC_REF(connp);
837 826 return;
838 827 }
839 828 }
840 829
841 830 ira->ira_flags |= IRAF_ICMP_ERROR;
842 831 if (IPCL_IS_TCP(connp)) {
843 832 SQUEUE_ENTER_ONE(connp->conn_sqp, mp,
844 833 connp->conn_recvicmp, connp, ira, SQ_FILL,
845 834 SQTAG_TCP6_INPUT_ICMP_ERR);
846 835 } else {
847 836 /* Not TCP; must be SOCK_RAW, IPPROTO_TCP */
848 837 ill_t *rill = ira->ira_rill;
849 838
850 839 ira->ira_ill = ira->ira_rill = NULL;
851 840 (connp->conn_recv)(connp, mp, NULL, ira);
852 841 CONN_DEC_REF(connp);
853 842 ira->ira_ill = ill;
854 843 ira->ira_rill = rill;
855 844 }
856 845 ira->ira_flags &= ~IRAF_ICMP_ERROR;
857 846 return;
858 847
859 848 }
860 849 case IPPROTO_SCTP:
861 850 up = (uint16_t *)((uchar_t *)ip6h + hdr_length);
862 851 /* Find a SCTP client stream for this packet. */
863 852 ((uint16_t *)&ports)[0] = up[1];
864 853 ((uint16_t *)&ports)[1] = up[0];
865 854
866 855 ira->ira_flags |= IRAF_ICMP_ERROR;
867 856 ip_fanout_sctp(mp, NULL, &rip6h, ports, ira);
868 857 ira->ira_flags &= ~IRAF_ICMP_ERROR;
869 858 return;
870 859
871 860 case IPPROTO_ESP:
872 861 case IPPROTO_AH:
873 862 if (!ipsec_loaded(ipss)) {
874 863 ip_proto_not_sup(mp, ira);
875 864 return;
876 865 }
877 866
878 867 if (nexthdr == IPPROTO_ESP)
879 868 mp = ipsecesp_icmp_error(mp, ira);
880 869 else
881 870 mp = ipsecah_icmp_error(mp, ira);
882 871 if (mp == NULL)
883 872 return;
884 873
885 874 /* Just in case ipsec didn't preserve the NULL b_cont */
886 875 if (mp->b_cont != NULL) {
887 876 if (!pullupmsg(mp, -1))
888 877 goto drop_pkt;
889 878 }
890 879
891 880 /*
892 881 * If succesful, the mp has been modified to not include
893 882 * the ESP/AH header so we can fanout to the ULP's icmp
894 883 * error handler.
895 884 */
896 885 if (mp->b_wptr - mp->b_rptr < IPV6_HDR_LEN)
897 886 goto drop_pkt;
898 887
899 888 ip6h = (ip6_t *)mp->b_rptr;
900 889 /* Don't call hdr_length_v6() unless you have to. */
901 890 if (ip6h->ip6_nxt != IPPROTO_ICMPV6)
902 891 hdr_length = ip_hdr_length_v6(mp, ip6h);
903 892 else
904 893 hdr_length = IPV6_HDR_LEN;
905 894
906 895 /* Verify the modified message before any further processes. */
907 896 icmp6 = (icmp6_t *)(&mp->b_rptr[hdr_length]);
908 897 if (!icmp_inbound_verify_v6(mp, icmp6, ira)) {
909 898 freemsg(mp);
910 899 return;
911 900 }
912 901
913 902 icmp_inbound_error_fanout_v6(mp, icmp6, ira);
914 903 return;
915 904
916 905 case IPPROTO_IPV6: {
917 906 /* Look for self-encapsulated packets that caused an error */
918 907 ip6_t *in_ip6h;
919 908
920 909 in_ip6h = (ip6_t *)((uint8_t *)ip6h + hdr_length);
921 910
922 911 if (IN6_ARE_ADDR_EQUAL(&in_ip6h->ip6_src, &ip6h->ip6_src) &&
923 912 IN6_ARE_ADDR_EQUAL(&in_ip6h->ip6_dst, &ip6h->ip6_dst)) {
924 913 /*
925 914 * Self-encapsulated case. As in the ipv4 case,
926 915 * we need to strip the 2nd IP header. Since mp
927 916 * is already pulled-up, we can simply bcopy
928 917 * the 3rd header + data over the 2nd header.
929 918 */
930 919 uint16_t unused_len;
931 920
932 921 /*
933 922 * Make sure we don't do recursion more than once.
934 923 */
935 924 if (!ip_hdr_length_nexthdr_v6(mp, in_ip6h,
936 925 &unused_len, &nexthdrp) ||
937 926 *nexthdrp == IPPROTO_IPV6) {
938 927 goto drop_pkt;
939 928 }
940 929
941 930 /*
942 931 * Copy the 3rd header + remaining data on top
943 932 * of the 2nd header.
944 933 */
945 934 bcopy(in_ip6h, ip6h, mp->b_wptr - (uchar_t *)in_ip6h);
946 935
947 936 /*
948 937 * Subtract length of the 2nd header.
949 938 */
950 939 mp->b_wptr -= hdr_length;
951 940
952 941 ip6h = (ip6_t *)mp->b_rptr;
953 942 /* Don't call hdr_length_v6() unless you have to. */
954 943 if (ip6h->ip6_nxt != IPPROTO_ICMPV6)
955 944 hdr_length = ip_hdr_length_v6(mp, ip6h);
956 945 else
957 946 hdr_length = IPV6_HDR_LEN;
958 947
959 948 /*
960 949 * Verify the modified message before any further
961 950 * processes.
962 951 */
963 952 icmp6 = (icmp6_t *)(&mp->b_rptr[hdr_length]);
964 953 if (!icmp_inbound_verify_v6(mp, icmp6, ira)) {
965 954 freemsg(mp);
966 955 return;
967 956 }
968 957
969 958 /*
970 959 * Now recurse, and see what I _really_ should be
971 960 * doing here.
972 961 */
973 962 icmp_inbound_error_fanout_v6(mp, icmp6, ira);
974 963 return;
975 964 }
976 965 /* FALLTHRU */
977 966 }
978 967 case IPPROTO_ENCAP:
979 968 if ((connp = ipcl_iptun_classify_v6(&rip6h.ip6_src,
980 969 &rip6h.ip6_dst, ipst)) != NULL) {
981 970 ira->ira_flags |= IRAF_ICMP_ERROR;
982 971 connp->conn_recvicmp(connp, mp, NULL, ira);
983 972 CONN_DEC_REF(connp);
984 973 ira->ira_flags &= ~IRAF_ICMP_ERROR;
985 974 return;
986 975 }
987 976 /*
988 977 * No IP tunnel is interested, fallthrough and see
989 978 * if a raw socket will want it.
990 979 */
991 980 /* FALLTHRU */
992 981 default:
993 982 ira->ira_flags |= IRAF_ICMP_ERROR;
994 983 ASSERT(ira->ira_protocol == nexthdr);
995 984 ip_fanout_proto_v6(mp, &rip6h, ira);
996 985 ira->ira_flags &= ~IRAF_ICMP_ERROR;
997 986 return;
998 987 }
999 988 /* NOTREACHED */
1000 989 drop_pkt:
1001 990 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInErrors);
1002 991 ip1dbg(("icmp_inbound_error_fanout_v6: drop pkt\n"));
1003 992 freemsg(mp);
1004 993 }
1005 994
1006 995 /*
1007 996 * Process received IPv6 ICMP Redirect messages.
1008 997 * Assumes the caller has verified that the headers are in the pulled up mblk.
1009 998 * Consumes mp.
1010 999 */
1011 1000 /* ARGSUSED */
1012 1001 static void
1013 1002 icmp_redirect_v6(mblk_t *mp, ip6_t *ip6h, nd_redirect_t *rd,
1014 1003 ip_recv_attr_t *ira)
1015 1004 {
1016 1005 ire_t *ire, *nire;
1017 1006 ire_t *prev_ire = NULL;
1018 1007 ire_t *redir_ire;
1019 1008 in6_addr_t *src, *dst, *gateway;
1020 1009 nd_opt_hdr_t *opt;
1021 1010 nce_t *nce;
1022 1011 int ncec_flags = 0;
1023 1012 int err = 0;
1024 1013 boolean_t redirect_to_router = B_FALSE;
1025 1014 int len;
1026 1015 int optlen;
1027 1016 ill_t *ill = ira->ira_rill;
1028 1017 ill_t *rill = ira->ira_rill;
1029 1018 ip_stack_t *ipst = ill->ill_ipst;
1030 1019
1031 1020 /*
1032 1021 * Since ira_ill is where the IRE_LOCAL was hosted we use ira_rill
1033 1022 * and make it be the IPMP upper so avoid being confused by a packet
1034 1023 * addressed to a unicast address on a different ill.
1035 1024 */
1036 1025 if (IS_UNDER_IPMP(rill)) {
1037 1026 rill = ipmp_ill_hold_ipmp_ill(rill);
1038 1027 if (rill == NULL) {
1039 1028 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInBadRedirects);
1040 1029 ip_drop_input("ipv6IfIcmpInBadRedirects - IPMP ill",
1041 1030 mp, ill);
1042 1031 freemsg(mp);
1043 1032 return;
1044 1033 }
1045 1034 ASSERT(rill != ira->ira_rill);
1046 1035 }
1047 1036
1048 1037 len = mp->b_wptr - (uchar_t *)rd;
1049 1038 src = &ip6h->ip6_src;
1050 1039 dst = &rd->nd_rd_dst;
1051 1040 gateway = &rd->nd_rd_target;
1052 1041
1053 1042 /* Verify if it is a valid redirect */
1054 1043 if (!IN6_IS_ADDR_LINKLOCAL(src) ||
1055 1044 (ip6h->ip6_hops != IPV6_MAX_HOPS) ||
1056 1045 (rd->nd_rd_code != 0) ||
1057 1046 (len < sizeof (nd_redirect_t)) ||
1058 1047 (IN6_IS_ADDR_V4MAPPED(dst)) ||
1059 1048 (IN6_IS_ADDR_MULTICAST(dst))) {
1060 1049 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInBadRedirects);
1061 1050 ip_drop_input("ipv6IfIcmpInBadRedirects - addr/len", mp, ill);
1062 1051 goto fail_redirect;
1063 1052 }
1064 1053
1065 1054 if (!(IN6_IS_ADDR_LINKLOCAL(gateway) ||
1066 1055 IN6_ARE_ADDR_EQUAL(gateway, dst))) {
1067 1056 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInBadRedirects);
1068 1057 ip_drop_input("ipv6IfIcmpInBadRedirects - bad gateway",
1069 1058 mp, ill);
1070 1059 goto fail_redirect;
1071 1060 }
1072 1061
1073 1062 optlen = len - sizeof (nd_redirect_t);
1074 1063 if (optlen != 0) {
1075 1064 if (!ndp_verify_optlen((nd_opt_hdr_t *)&rd[1], optlen)) {
1076 1065 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInBadRedirects);
1077 1066 ip_drop_input("ipv6IfIcmpInBadRedirects - options",
1078 1067 mp, ill);
1079 1068 goto fail_redirect;
1080 1069 }
1081 1070 }
1082 1071
1083 1072 if (!IN6_ARE_ADDR_EQUAL(gateway, dst)) {
1084 1073 redirect_to_router = B_TRUE;
1085 1074 ncec_flags |= NCE_F_ISROUTER;
1086 1075 } else {
1087 1076 gateway = dst; /* Add nce for dst */
1088 1077 }
1089 1078
1090 1079
1091 1080 /*
1092 1081 * Verify that the IP source address of the redirect is
1093 1082 * the same as the current first-hop router for the specified
1094 1083 * ICMP destination address.
1095 1084 * Also, Make sure we had a route for the dest in question and
1096 1085 * that route was pointing to the old gateway (the source of the
1097 1086 * redirect packet.)
1098 1087 * We do longest match and then compare ire_gateway_addr_v6 below.
1099 1088 */
1100 1089 prev_ire = ire_ftable_lookup_v6(dst, 0, 0, 0, rill,
1101 1090 ALL_ZONES, NULL, MATCH_IRE_ILL, 0, ipst, NULL);
1102 1091
1103 1092 /*
1104 1093 * Check that
1105 1094 * the redirect was not from ourselves
1106 1095 * old gateway is still directly reachable
1107 1096 */
1108 1097 if (prev_ire == NULL ||
1109 1098 (prev_ire->ire_type & (IRE_LOCAL|IRE_LOOPBACK)) ||
1110 1099 (prev_ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) ||
1111 1100 !IN6_ARE_ADDR_EQUAL(src, &prev_ire->ire_gateway_addr_v6)) {
1112 1101 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInBadRedirects);
1113 1102 ip_drop_input("ipv6IfIcmpInBadRedirects - ire", mp, ill);
1114 1103 goto fail_redirect;
1115 1104 }
1116 1105
1117 1106 ASSERT(prev_ire->ire_ill != NULL);
1118 1107 if (prev_ire->ire_ill->ill_flags & ILLF_NONUD)
1119 1108 ncec_flags |= NCE_F_NONUD;
1120 1109
1121 1110 opt = (nd_opt_hdr_t *)&rd[1];
1122 1111 opt = ndp_get_option(opt, optlen, ND_OPT_TARGET_LINKADDR);
1123 1112 if (opt != NULL) {
1124 1113 err = nce_lookup_then_add_v6(rill,
1125 1114 (uchar_t *)&opt[1], /* Link layer address */
1126 1115 rill->ill_phys_addr_length,
1127 1116 gateway, ncec_flags, ND_STALE, &nce);
1128 1117 switch (err) {
1129 1118 case 0:
1130 1119 nce_refrele(nce);
1131 1120 break;
1132 1121 case EEXIST:
1133 1122 /*
1134 1123 * Check to see if link layer address has changed and
1135 1124 * process the ncec_state accordingly.
1136 1125 */
1137 1126 nce_process(nce->nce_common,
1138 1127 (uchar_t *)&opt[1], 0, B_FALSE);
1139 1128 nce_refrele(nce);
1140 1129 break;
1141 1130 default:
1142 1131 ip1dbg(("icmp_redirect_v6: NCE create failed %d\n",
1143 1132 err));
1144 1133 goto fail_redirect;
1145 1134 }
1146 1135 }
1147 1136 if (redirect_to_router) {
1148 1137 ASSERT(IN6_IS_ADDR_LINKLOCAL(gateway));
1149 1138
1150 1139 /*
1151 1140 * Create a Route Association. This will allow us to remember
1152 1141 * a router told us to use the particular gateway.
1153 1142 */
1154 1143 ire = ire_create_v6(
1155 1144 dst,
1156 1145 &ipv6_all_ones, /* mask */
1157 1146 gateway, /* gateway addr */
1158 1147 IRE_HOST,
1159 1148 prev_ire->ire_ill,
1160 1149 ALL_ZONES,
1161 1150 (RTF_DYNAMIC | RTF_GATEWAY | RTF_HOST),
1162 1151 NULL,
1163 1152 ipst);
1164 1153 } else {
1165 1154 ipif_t *ipif;
1166 1155 in6_addr_t gw;
1167 1156
1168 1157 /*
1169 1158 * Just create an on link entry, i.e. interface route.
1170 1159 * The gateway field is our link-local on the ill.
1171 1160 */
1172 1161 mutex_enter(&rill->ill_lock);
1173 1162 for (ipif = rill->ill_ipif; ipif != NULL;
1174 1163 ipif = ipif->ipif_next) {
1175 1164 if (!(ipif->ipif_state_flags & IPIF_CONDEMNED) &&
1176 1165 IN6_IS_ADDR_LINKLOCAL(&ipif->ipif_v6lcl_addr))
1177 1166 break;
1178 1167 }
1179 1168 if (ipif == NULL) {
1180 1169 /* We have no link-local address! */
1181 1170 mutex_exit(&rill->ill_lock);
1182 1171 goto fail_redirect;
1183 1172 }
1184 1173 gw = ipif->ipif_v6lcl_addr;
1185 1174 mutex_exit(&rill->ill_lock);
1186 1175
1187 1176 ire = ire_create_v6(
1188 1177 dst, /* gateway == dst */
1189 1178 &ipv6_all_ones, /* mask */
1190 1179 &gw, /* gateway addr */
1191 1180 rill->ill_net_type, /* IF_[NO]RESOLVER */
1192 1181 prev_ire->ire_ill,
1193 1182 ALL_ZONES,
1194 1183 (RTF_DYNAMIC | RTF_HOST),
1195 1184 NULL,
1196 1185 ipst);
1197 1186 }
1198 1187
1199 1188 if (ire == NULL)
1200 1189 goto fail_redirect;
1201 1190
1202 1191 nire = ire_add(ire);
1203 1192 /* Check if it was a duplicate entry */
1204 1193 if (nire != NULL && nire != ire) {
1205 1194 ASSERT(nire->ire_identical_ref > 1);
1206 1195 ire_delete(nire);
1207 1196 ire_refrele(nire);
1208 1197 nire = NULL;
1209 1198 }
1210 1199 ire = nire;
1211 1200 if (ire != NULL) {
1212 1201 ire_refrele(ire); /* Held in ire_add */
1213 1202
1214 1203 /* tell routing sockets that we received a redirect */
1215 1204 ip_rts_change_v6(RTM_REDIRECT,
1216 1205 &rd->nd_rd_dst,
1217 1206 &rd->nd_rd_target,
1218 1207 &ipv6_all_ones, 0, src,
1219 1208 (RTF_DYNAMIC | RTF_GATEWAY | RTF_HOST), 0,
1220 1209 (RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_AUTHOR), ipst);
1221 1210
1222 1211 /*
1223 1212 * Delete any existing IRE_HOST type ires for this destination.
1224 1213 * This together with the added IRE has the effect of
1225 1214 * modifying an existing redirect.
1226 1215 */
1227 1216 redir_ire = ire_ftable_lookup_v6(dst, 0, src, IRE_HOST,
1228 1217 prev_ire->ire_ill, ALL_ZONES, NULL,
1229 1218 (MATCH_IRE_GW | MATCH_IRE_TYPE | MATCH_IRE_ILL), 0, ipst,
1230 1219 NULL);
1231 1220
1232 1221 if (redir_ire != NULL) {
1233 1222 if (redir_ire->ire_flags & RTF_DYNAMIC)
1234 1223 ire_delete(redir_ire);
1235 1224 ire_refrele(redir_ire);
1236 1225 }
1237 1226 }
1238 1227
1239 1228 ire_refrele(prev_ire);
1240 1229 prev_ire = NULL;
1241 1230
1242 1231 fail_redirect:
1243 1232 if (prev_ire != NULL)
1244 1233 ire_refrele(prev_ire);
1245 1234 freemsg(mp);
1246 1235 if (rill != ira->ira_rill)
1247 1236 ill_refrele(rill);
1248 1237 }
1249 1238
1250 1239 /*
1251 1240 * Build and ship an IPv6 ICMP message using the packet data in mp,
1252 1241 * and the ICMP header pointed to by "stuff". (May be called as
1253 1242 * writer.)
1254 1243 * Note: assumes that icmp_pkt_err_ok_v6 has been called to
1255 1244 * verify that an icmp error packet can be sent.
1256 1245 *
1257 1246 * If v6src_ptr is set use it as a source. Otherwise select a reasonable
1258 1247 * source address (see above function).
1259 1248 */
1260 1249 static void
1261 1250 icmp_pkt_v6(mblk_t *mp, void *stuff, size_t len,
1262 1251 const in6_addr_t *v6src_ptr, ip_recv_attr_t *ira)
1263 1252 {
1264 1253 ip6_t *ip6h;
1265 1254 in6_addr_t v6dst;
1266 1255 size_t len_needed;
1267 1256 size_t msg_len;
1268 1257 mblk_t *mp1;
1269 1258 icmp6_t *icmp6;
1270 1259 in6_addr_t v6src;
1271 1260 ill_t *ill = ira->ira_ill;
1272 1261 ip_stack_t *ipst = ill->ill_ipst;
1273 1262 ip_xmit_attr_t ixas;
1274 1263
1275 1264 ip6h = (ip6_t *)mp->b_rptr;
1276 1265
1277 1266 bzero(&ixas, sizeof (ixas));
1278 1267 ixas.ixa_flags = IXAF_BASIC_SIMPLE_V6;
1279 1268 ixas.ixa_zoneid = ira->ira_zoneid;
1280 1269 ixas.ixa_ifindex = 0;
1281 1270 ixas.ixa_ipst = ipst;
1282 1271 ixas.ixa_cred = kcred;
1283 1272 ixas.ixa_cpid = NOPID;
1284 1273 ixas.ixa_tsl = ira->ira_tsl; /* Behave as a multi-level responder */
1285 1274 ixas.ixa_multicast_ttl = IP_DEFAULT_MULTICAST_TTL;
1286 1275
1287 1276 /*
1288 1277 * If the source of the original packet was link-local, then
1289 1278 * make sure we send on the same ill (group) as we received it on.
1290 1279 */
1291 1280 if (IN6_IS_ADDR_LINKSCOPE(&ip6h->ip6_src)) {
1292 1281 ixas.ixa_flags |= IXAF_SCOPEID_SET;
1293 1282 if (IS_UNDER_IPMP(ill))
1294 1283 ixas.ixa_scopeid = ill_get_upper_ifindex(ill);
1295 1284 else
1296 1285 ixas.ixa_scopeid = ill->ill_phyint->phyint_ifindex;
1297 1286 }
1298 1287
1299 1288 if (ira->ira_flags & IRAF_IPSEC_SECURE) {
1300 1289 /*
1301 1290 * Apply IPsec based on how IPsec was applied to
1302 1291 * the packet that had the error.
1303 1292 *
1304 1293 * If it was an outbound packet that caused the ICMP
1305 1294 * error, then the caller will have setup the IRA
1306 1295 * appropriately.
1307 1296 */
1308 1297 if (!ipsec_in_to_out(ira, &ixas, mp, NULL, ip6h)) {
1309 1298 BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsOutDiscards);
1310 1299 /* Note: mp already consumed and ip_drop_packet done */
1311 1300 return;
1312 1301 }
1313 1302 } else {
1314 1303 /*
1315 1304 * This is in clear. The icmp message we are building
1316 1305 * here should go out in clear, independent of our policy.
1317 1306 */
1318 1307 ixas.ixa_flags |= IXAF_NO_IPSEC;
1319 1308 }
1320 1309
1321 1310 /*
1322 1311 * If the caller specified the source we use that.
1323 1312 * Otherwise, if the packet was for one of our unicast addresses, make
1324 1313 * sure we respond with that as the source. Otherwise
1325 1314 * have ip_output_simple pick the source address.
1326 1315 */
1327 1316 if (v6src_ptr != NULL) {
1328 1317 v6src = *v6src_ptr;
1329 1318 } else {
1330 1319 ire_t *ire;
1331 1320 uint_t match_flags = MATCH_IRE_TYPE | MATCH_IRE_ZONEONLY;
1332 1321
1333 1322 if (IN6_IS_ADDR_LINKLOCAL(&ip6h->ip6_src) ||
1334 1323 IN6_IS_ADDR_LINKLOCAL(&ip6h->ip6_dst))
1335 1324 match_flags |= MATCH_IRE_ILL;
1336 1325
1337 1326 ire = ire_ftable_lookup_v6(&ip6h->ip6_dst, 0, 0,
1338 1327 (IRE_LOCAL|IRE_LOOPBACK), ill, ira->ira_zoneid, NULL,
1339 1328 match_flags, 0, ipst, NULL);
1340 1329 if (ire != NULL) {
1341 1330 v6src = ip6h->ip6_dst;
1342 1331 ire_refrele(ire);
1343 1332 } else {
1344 1333 v6src = ipv6_all_zeros;
1345 1334 ixas.ixa_flags |= IXAF_SET_SOURCE;
1346 1335 }
1347 1336 }
1348 1337 v6dst = ip6h->ip6_src;
1349 1338 len_needed = ipst->ips_ipv6_icmp_return - IPV6_HDR_LEN - len;
1350 1339 msg_len = msgdsize(mp);
1351 1340 if (msg_len > len_needed) {
1352 1341 if (!adjmsg(mp, len_needed - msg_len)) {
1353 1342 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutErrors);
1354 1343 freemsg(mp);
1355 1344 return;
1356 1345 }
1357 1346 msg_len = len_needed;
1358 1347 }
1359 1348 mp1 = allocb(IPV6_HDR_LEN + len, BPRI_MED);
1360 1349 if (mp1 == NULL) {
1361 1350 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutErrors);
1362 1351 freemsg(mp);
1363 1352 return;
1364 1353 }
1365 1354 mp1->b_cont = mp;
1366 1355 mp = mp1;
1367 1356
1368 1357 /*
1369 1358 * Set IXAF_TRUSTED_ICMP so we can let the ICMP messages this
1370 1359 * node generates be accepted in peace by all on-host destinations.
1371 1360 * If we do NOT assume that all on-host destinations trust
1372 1361 * self-generated ICMP messages, then rework here, ip6.c, and spd.c.
1373 1362 * (Look for IXAF_TRUSTED_ICMP).
1374 1363 */
1375 1364 ixas.ixa_flags |= IXAF_TRUSTED_ICMP;
1376 1365
1377 1366 ip6h = (ip6_t *)mp->b_rptr;
1378 1367 mp1->b_wptr = (uchar_t *)ip6h + (IPV6_HDR_LEN + len);
1379 1368
1380 1369 ip6h->ip6_vcf = IPV6_DEFAULT_VERS_AND_FLOW;
1381 1370 ip6h->ip6_nxt = IPPROTO_ICMPV6;
1382 1371 ip6h->ip6_hops = ipst->ips_ipv6_def_hops;
1383 1372 ip6h->ip6_dst = v6dst;
1384 1373 ip6h->ip6_src = v6src;
1385 1374 msg_len += IPV6_HDR_LEN + len;
1386 1375 if (msg_len > IP_MAXPACKET + IPV6_HDR_LEN) {
1387 1376 (void) adjmsg(mp, IP_MAXPACKET + IPV6_HDR_LEN - msg_len);
1388 1377 msg_len = IP_MAXPACKET + IPV6_HDR_LEN;
1389 1378 }
1390 1379 ip6h->ip6_plen = htons((uint16_t)(msgdsize(mp) - IPV6_HDR_LEN));
1391 1380 icmp6 = (icmp6_t *)&ip6h[1];
1392 1381 bcopy(stuff, (char *)icmp6, len);
1393 1382 /*
1394 1383 * Prepare for checksum by putting icmp length in the icmp
1395 1384 * checksum field. The checksum is calculated in ip_output_wire_v6.
1396 1385 */
1397 1386 icmp6->icmp6_cksum = ip6h->ip6_plen;
1398 1387 if (icmp6->icmp6_type == ND_REDIRECT) {
1399 1388 ip6h->ip6_hops = IPV6_MAX_HOPS;
1400 1389 }
1401 1390
1402 1391 (void) ip_output_simple(mp, &ixas);
1403 1392 ixa_cleanup(&ixas);
1404 1393 }
1405 1394
1406 1395 /*
1407 1396 * Update the output mib when ICMPv6 packets are sent.
1408 1397 */
1409 1398 void
1410 1399 icmp_update_out_mib_v6(ill_t *ill, icmp6_t *icmp6)
1411 1400 {
1412 1401 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutMsgs);
1413 1402
1414 1403 switch (icmp6->icmp6_type) {
1415 1404 case ICMP6_DST_UNREACH:
1416 1405 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutDestUnreachs);
1417 1406 if (icmp6->icmp6_code == ICMP6_DST_UNREACH_ADMIN)
1418 1407 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutAdminProhibs);
1419 1408 break;
1420 1409
1421 1410 case ICMP6_TIME_EXCEEDED:
1422 1411 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutTimeExcds);
1423 1412 break;
1424 1413
1425 1414 case ICMP6_PARAM_PROB:
1426 1415 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutParmProblems);
1427 1416 break;
1428 1417
1429 1418 case ICMP6_PACKET_TOO_BIG:
1430 1419 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutPktTooBigs);
1431 1420 break;
1432 1421
1433 1422 case ICMP6_ECHO_REQUEST:
1434 1423 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutEchos);
1435 1424 break;
1436 1425
1437 1426 case ICMP6_ECHO_REPLY:
1438 1427 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutEchoReplies);
1439 1428 break;
1440 1429
1441 1430 case ND_ROUTER_SOLICIT:
1442 1431 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutRouterSolicits);
1443 1432 break;
1444 1433
1445 1434 case ND_ROUTER_ADVERT:
1446 1435 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutRouterAdvertisements);
1447 1436 break;
1448 1437
1449 1438 case ND_NEIGHBOR_SOLICIT:
1450 1439 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutNeighborSolicits);
1451 1440 break;
1452 1441
1453 1442 case ND_NEIGHBOR_ADVERT:
1454 1443 BUMP_MIB(ill->ill_icmp6_mib,
1455 1444 ipv6IfIcmpOutNeighborAdvertisements);
1456 1445 break;
1457 1446
1458 1447 case ND_REDIRECT:
1459 1448 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutRedirects);
1460 1449 break;
1461 1450
1462 1451 case MLD_LISTENER_QUERY:
1463 1452 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutGroupMembQueries);
1464 1453 break;
1465 1454
1466 1455 case MLD_LISTENER_REPORT:
1467 1456 case MLD_V2_LISTENER_REPORT:
1468 1457 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutGroupMembResponses);
1469 1458 break;
1470 1459
1471 1460 case MLD_LISTENER_REDUCTION:
1472 1461 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutGroupMembReductions);
1473 1462 break;
1474 1463 }
1475 1464 }
1476 1465
1477 1466 /*
1478 1467 * Check if it is ok to send an ICMPv6 error packet in
1479 1468 * response to the IP packet in mp.
1480 1469 * Free the message and return null if no
1481 1470 * ICMP error packet should be sent.
1482 1471 */
1483 1472 static mblk_t *
1484 1473 icmp_pkt_err_ok_v6(mblk_t *mp, boolean_t mcast_ok, ip_recv_attr_t *ira)
1485 1474 {
1486 1475 ill_t *ill = ira->ira_ill;
1487 1476 ip_stack_t *ipst = ill->ill_ipst;
1488 1477 boolean_t llbcast;
1489 1478 ip6_t *ip6h;
1490 1479
1491 1480 if (!mp)
1492 1481 return (NULL);
1493 1482
1494 1483 /* We view multicast and broadcast as the same.. */
1495 1484 llbcast = (ira->ira_flags &
1496 1485 (IRAF_L2DST_MULTICAST|IRAF_L2DST_BROADCAST)) != 0;
1497 1486 ip6h = (ip6_t *)mp->b_rptr;
1498 1487
1499 1488 /* Check if source address uniquely identifies the host */
1500 1489
1501 1490 if (IN6_IS_ADDR_MULTICAST(&ip6h->ip6_src) ||
1502 1491 IN6_IS_ADDR_V4MAPPED(&ip6h->ip6_src) ||
1503 1492 IN6_IS_ADDR_UNSPECIFIED(&ip6h->ip6_src)) {
1504 1493 freemsg(mp);
1505 1494 return (NULL);
1506 1495 }
1507 1496
1508 1497 if (ip6h->ip6_nxt == IPPROTO_ICMPV6) {
1509 1498 size_t len_needed = IPV6_HDR_LEN + ICMP6_MINLEN;
1510 1499 icmp6_t *icmp6;
1511 1500
1512 1501 if (mp->b_wptr - mp->b_rptr < len_needed) {
1513 1502 if (!pullupmsg(mp, len_needed)) {
1514 1503 BUMP_MIB(ill->ill_icmp6_mib,
1515 1504 ipv6IfIcmpInErrors);
1516 1505 freemsg(mp);
1517 1506 return (NULL);
1518 1507 }
1519 1508 ip6h = (ip6_t *)mp->b_rptr;
1520 1509 }
1521 1510 icmp6 = (icmp6_t *)&ip6h[1];
1522 1511 /* Explicitly do not generate errors in response to redirects */
1523 1512 if (ICMP6_IS_ERROR(icmp6->icmp6_type) ||
1524 1513 icmp6->icmp6_type == ND_REDIRECT) {
1525 1514 freemsg(mp);
1526 1515 return (NULL);
1527 1516 }
1528 1517 }
1529 1518 /*
1530 1519 * Check that the destination is not multicast and that the packet
1531 1520 * was not sent on link layer broadcast or multicast. (Exception
1532 1521 * is Packet too big message as per the draft - when mcast_ok is set.)
1533 1522 */
1534 1523 if (!mcast_ok &&
1535 1524 (llbcast || IN6_IS_ADDR_MULTICAST(&ip6h->ip6_dst))) {
1536 1525 freemsg(mp);
1537 1526 return (NULL);
1538 1527 }
1539 1528 /*
1540 1529 * If this is a labeled system, then check to see if we're allowed to
1541 1530 * send a response to this particular sender. If not, then just drop.
1542 1531 */
1543 1532 if (is_system_labeled() && !tsol_can_reply_error(mp, ira)) {
1544 1533 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutErrors);
1545 1534 freemsg(mp);
1546 1535 return (NULL);
1547 1536 }
1548 1537
1549 1538 if (icmp_err_rate_limit(ipst)) {
1550 1539 /*
1551 1540 * Only send ICMP error packets every so often.
1552 1541 * This should be done on a per port/source basis,
1553 1542 * but for now this will suffice.
1554 1543 */
1555 1544 freemsg(mp);
1556 1545 return (NULL);
1557 1546 }
1558 1547 return (mp);
1559 1548 }
1560 1549
1561 1550 /*
1562 1551 * Called when a packet was sent out the same link that it arrived on.
1563 1552 * Check if it is ok to send a redirect and then send it.
1564 1553 */
1565 1554 void
1566 1555 ip_send_potential_redirect_v6(mblk_t *mp, ip6_t *ip6h, ire_t *ire,
1567 1556 ip_recv_attr_t *ira)
1568 1557 {
1569 1558 ill_t *ill = ira->ira_ill;
1570 1559 ip_stack_t *ipst = ill->ill_ipst;
1571 1560 in6_addr_t *v6targ;
1572 1561 ire_t *src_ire_v6 = NULL;
1573 1562 mblk_t *mp1;
1574 1563 ire_t *nhop_ire = NULL;
1575 1564
1576 1565 /*
1577 1566 * Don't send a redirect when forwarding a source
1578 1567 * routed packet.
1579 1568 */
1580 1569 if (ip_source_routed_v6(ip6h, mp, ipst))
1581 1570 return;
1582 1571
1583 1572 if (ire->ire_type & IRE_ONLINK) {
1584 1573 /* Target is directly connected */
1585 1574 v6targ = &ip6h->ip6_dst;
1586 1575 } else {
1587 1576 /* Determine the most specific IRE used to send the packets */
1588 1577 nhop_ire = ire_nexthop(ire);
1589 1578 if (nhop_ire == NULL)
1590 1579 return;
1591 1580
1592 1581 /*
1593 1582 * We won't send redirects to a router
1594 1583 * that doesn't have a link local
1595 1584 * address, but will forward.
1596 1585 */
1597 1586 if (!IN6_IS_ADDR_LINKLOCAL(&nhop_ire->ire_addr_v6)) {
1598 1587 BUMP_MIB(ill->ill_ip_mib, ipIfStatsInAddrErrors);
1599 1588 ip_drop_input("ipIfStatsInAddrErrors", mp, ill);
1600 1589 ire_refrele(nhop_ire);
1601 1590 return;
1602 1591 }
1603 1592 v6targ = &nhop_ire->ire_addr_v6;
1604 1593 }
1605 1594 src_ire_v6 = ire_ftable_lookup_v6(&ip6h->ip6_src,
1606 1595 NULL, NULL, IRE_INTERFACE, ire->ire_ill, ALL_ZONES, NULL,
1607 1596 MATCH_IRE_ILL | MATCH_IRE_TYPE, 0, ipst, NULL);
1608 1597
1609 1598 if (src_ire_v6 == NULL) {
1610 1599 if (nhop_ire != NULL)
1611 1600 ire_refrele(nhop_ire);
1612 1601 return;
1613 1602 }
1614 1603
1615 1604 /*
1616 1605 * The source is directly connected.
1617 1606 */
1618 1607 mp1 = copymsg(mp);
1619 1608 if (mp1 != NULL)
1620 1609 icmp_send_redirect_v6(mp1, v6targ, &ip6h->ip6_dst, ira);
1621 1610
1622 1611 if (nhop_ire != NULL)
1623 1612 ire_refrele(nhop_ire);
1624 1613 ire_refrele(src_ire_v6);
1625 1614 }
1626 1615
1627 1616 /*
1628 1617 * Generate an ICMPv6 redirect message.
1629 1618 * Include target link layer address option if it exits.
1630 1619 * Always include redirect header.
1631 1620 */
1632 1621 static void
1633 1622 icmp_send_redirect_v6(mblk_t *mp, in6_addr_t *targetp, in6_addr_t *dest,
1634 1623 ip_recv_attr_t *ira)
1635 1624 {
1636 1625 nd_redirect_t *rd;
1637 1626 nd_opt_rd_hdr_t *rdh;
1638 1627 uchar_t *buf;
1639 1628 ncec_t *ncec = NULL;
1640 1629 nd_opt_hdr_t *opt;
1641 1630 int len;
1642 1631 int ll_opt_len = 0;
1643 1632 int max_redir_hdr_data_len;
1644 1633 int pkt_len;
1645 1634 in6_addr_t *srcp;
1646 1635 ill_t *ill;
1647 1636 boolean_t need_refrele;
1648 1637 ip_stack_t *ipst = ira->ira_ill->ill_ipst;
1649 1638
1650 1639 mp = icmp_pkt_err_ok_v6(mp, B_FALSE, ira);
1651 1640 if (mp == NULL)
1652 1641 return;
1653 1642
1654 1643 if (IS_UNDER_IPMP(ira->ira_ill)) {
1655 1644 ill = ipmp_ill_hold_ipmp_ill(ira->ira_ill);
1656 1645 if (ill == NULL) {
1657 1646 ill = ira->ira_ill;
1658 1647 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInBadRedirects);
1659 1648 ip_drop_output("no IPMP ill for sending redirect",
1660 1649 mp, ill);
1661 1650 freemsg(mp);
1662 1651 return;
1663 1652 }
1664 1653 need_refrele = B_TRUE;
1665 1654 } else {
1666 1655 ill = ira->ira_ill;
1667 1656 need_refrele = B_FALSE;
1668 1657 }
1669 1658
1670 1659 ncec = ncec_lookup_illgrp_v6(ill, targetp);
1671 1660 if (ncec != NULL && ncec->ncec_state != ND_INCOMPLETE &&
1672 1661 ncec->ncec_lladdr != NULL) {
1673 1662 ll_opt_len = (sizeof (nd_opt_hdr_t) +
1674 1663 ill->ill_phys_addr_length + 7)/8 * 8;
1675 1664 }
1676 1665 len = sizeof (nd_redirect_t) + sizeof (nd_opt_rd_hdr_t) + ll_opt_len;
1677 1666 ASSERT(len % 4 == 0);
1678 1667 buf = kmem_alloc(len, KM_NOSLEEP);
1679 1668 if (buf == NULL) {
1680 1669 if (ncec != NULL)
1681 1670 ncec_refrele(ncec);
1682 1671 if (need_refrele)
1683 1672 ill_refrele(ill);
1684 1673 freemsg(mp);
1685 1674 return;
1686 1675 }
1687 1676
1688 1677 rd = (nd_redirect_t *)buf;
1689 1678 rd->nd_rd_type = (uint8_t)ND_REDIRECT;
1690 1679 rd->nd_rd_code = 0;
1691 1680 rd->nd_rd_reserved = 0;
1692 1681 rd->nd_rd_target = *targetp;
1693 1682 rd->nd_rd_dst = *dest;
1694 1683
1695 1684 opt = (nd_opt_hdr_t *)(buf + sizeof (nd_redirect_t));
1696 1685 if (ncec != NULL && ll_opt_len != 0) {
1697 1686 opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
1698 1687 opt->nd_opt_len = ll_opt_len/8;
1699 1688 bcopy((char *)ncec->ncec_lladdr, &opt[1],
1700 1689 ill->ill_phys_addr_length);
1701 1690 }
1702 1691 if (ncec != NULL)
1703 1692 ncec_refrele(ncec);
1704 1693 rdh = (nd_opt_rd_hdr_t *)(buf + sizeof (nd_redirect_t) + ll_opt_len);
1705 1694 rdh->nd_opt_rh_type = (uint8_t)ND_OPT_REDIRECTED_HEADER;
1706 1695 /* max_redir_hdr_data_len and nd_opt_rh_len must be multiple of 8 */
1707 1696 max_redir_hdr_data_len =
1708 1697 (ipst->ips_ipv6_icmp_return - IPV6_HDR_LEN - len)/8*8;
1709 1698 pkt_len = msgdsize(mp);
1710 1699 /* Make sure mp is 8 byte aligned */
1711 1700 if (pkt_len > max_redir_hdr_data_len) {
1712 1701 rdh->nd_opt_rh_len = (max_redir_hdr_data_len +
1713 1702 sizeof (nd_opt_rd_hdr_t))/8;
1714 1703 (void) adjmsg(mp, max_redir_hdr_data_len - pkt_len);
1715 1704 } else {
1716 1705 rdh->nd_opt_rh_len = (pkt_len + sizeof (nd_opt_rd_hdr_t))/8;
1717 1706 (void) adjmsg(mp, -(pkt_len % 8));
1718 1707 }
1719 1708 rdh->nd_opt_rh_reserved1 = 0;
1720 1709 rdh->nd_opt_rh_reserved2 = 0;
1721 1710 /* ipif_v6lcl_addr contains the link-local source address */
1722 1711 srcp = &ill->ill_ipif->ipif_v6lcl_addr;
1723 1712
1724 1713 /* Redirects sent by router, and router is global zone */
1725 1714 ASSERT(ira->ira_zoneid == ALL_ZONES);
1726 1715 ira->ira_zoneid = GLOBAL_ZONEID;
1727 1716 icmp_pkt_v6(mp, buf, len, srcp, ira);
1728 1717 kmem_free(buf, len);
1729 1718 if (need_refrele)
1730 1719 ill_refrele(ill);
1731 1720 }
1732 1721
1733 1722
1734 1723 /* Generate an ICMP time exceeded message. (May be called as writer.) */
1735 1724 void
1736 1725 icmp_time_exceeded_v6(mblk_t *mp, uint8_t code, boolean_t mcast_ok,
1737 1726 ip_recv_attr_t *ira)
1738 1727 {
1739 1728 icmp6_t icmp6;
1740 1729
1741 1730 mp = icmp_pkt_err_ok_v6(mp, mcast_ok, ira);
1742 1731 if (mp == NULL)
1743 1732 return;
1744 1733
1745 1734 bzero(&icmp6, sizeof (icmp6_t));
1746 1735 icmp6.icmp6_type = ICMP6_TIME_EXCEEDED;
1747 1736 icmp6.icmp6_code = code;
1748 1737 icmp_pkt_v6(mp, &icmp6, sizeof (icmp6_t), NULL, ira);
1749 1738 }
1750 1739
1751 1740 /*
1752 1741 * Generate an ICMP unreachable message.
1753 1742 * When called from ip_output side a minimal ip_recv_attr_t needs to be
1754 1743 * constructed by the caller.
1755 1744 */
1756 1745 void
1757 1746 icmp_unreachable_v6(mblk_t *mp, uint8_t code, boolean_t mcast_ok,
1758 1747 ip_recv_attr_t *ira)
1759 1748 {
1760 1749 icmp6_t icmp6;
1761 1750
1762 1751 mp = icmp_pkt_err_ok_v6(mp, mcast_ok, ira);
1763 1752 if (mp == NULL)
1764 1753 return;
1765 1754
1766 1755 bzero(&icmp6, sizeof (icmp6_t));
1767 1756 icmp6.icmp6_type = ICMP6_DST_UNREACH;
1768 1757 icmp6.icmp6_code = code;
1769 1758 icmp_pkt_v6(mp, &icmp6, sizeof (icmp6_t), NULL, ira);
1770 1759 }
1771 1760
1772 1761 /*
1773 1762 * Generate an ICMP pkt too big message.
1774 1763 * When called from ip_output side a minimal ip_recv_attr_t needs to be
1775 1764 * constructed by the caller.
1776 1765 */
1777 1766 void
1778 1767 icmp_pkt2big_v6(mblk_t *mp, uint32_t mtu, boolean_t mcast_ok,
1779 1768 ip_recv_attr_t *ira)
1780 1769 {
1781 1770 icmp6_t icmp6;
1782 1771
1783 1772 mp = icmp_pkt_err_ok_v6(mp, mcast_ok, ira);
1784 1773 if (mp == NULL)
1785 1774 return;
1786 1775
1787 1776 bzero(&icmp6, sizeof (icmp6_t));
1788 1777 icmp6.icmp6_type = ICMP6_PACKET_TOO_BIG;
1789 1778 icmp6.icmp6_code = 0;
1790 1779 icmp6.icmp6_mtu = htonl(mtu);
1791 1780
1792 1781 icmp_pkt_v6(mp, &icmp6, sizeof (icmp6_t), NULL, ira);
1793 1782 }
1794 1783
1795 1784 /*
1796 1785 * Generate an ICMP parameter problem message. (May be called as writer.)
1797 1786 * 'offset' is the offset from the beginning of the packet in error.
1798 1787 * When called from ip_output side a minimal ip_recv_attr_t needs to be
1799 1788 * constructed by the caller.
1800 1789 */
1801 1790 static void
1802 1791 icmp_param_problem_v6(mblk_t *mp, uint8_t code, uint32_t offset,
1803 1792 boolean_t mcast_ok, ip_recv_attr_t *ira)
1804 1793 {
1805 1794 icmp6_t icmp6;
1806 1795
1807 1796 mp = icmp_pkt_err_ok_v6(mp, mcast_ok, ira);
1808 1797 if (mp == NULL)
1809 1798 return;
1810 1799
1811 1800 bzero((char *)&icmp6, sizeof (icmp6_t));
1812 1801 icmp6.icmp6_type = ICMP6_PARAM_PROB;
1813 1802 icmp6.icmp6_code = code;
1814 1803 icmp6.icmp6_pptr = htonl(offset);
1815 1804 icmp_pkt_v6(mp, &icmp6, sizeof (icmp6_t), NULL, ira);
1816 1805 }
1817 1806
1818 1807 void
1819 1808 icmp_param_problem_nexthdr_v6(mblk_t *mp, boolean_t mcast_ok,
1820 1809 ip_recv_attr_t *ira)
1821 1810 {
1822 1811 ip6_t *ip6h = (ip6_t *)mp->b_rptr;
1823 1812 uint16_t hdr_length;
1824 1813 uint8_t *nexthdrp;
1825 1814 uint32_t offset;
1826 1815 ill_t *ill = ira->ira_ill;
1827 1816
1828 1817 /* Determine the offset of the bad nexthdr value */
1829 1818 if (!ip_hdr_length_nexthdr_v6(mp, ip6h, &hdr_length, &nexthdrp)) {
1830 1819 /* Malformed packet */
1831 1820 BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards);
1832 1821 ip_drop_input("ipIfStatsInDiscards", mp, ill);
1833 1822 freemsg(mp);
1834 1823 return;
1835 1824 }
1836 1825
1837 1826 offset = nexthdrp - mp->b_rptr;
1838 1827 icmp_param_problem_v6(mp, ICMP6_PARAMPROB_NEXTHEADER, offset,
1839 1828 mcast_ok, ira);
1840 1829 }
1841 1830
1842 1831 /*
1843 1832 * Verify whether or not the IP address is a valid local address.
1844 1833 * Could be a unicast, including one for a down interface.
1845 1834 * If allow_mcbc then a multicast or broadcast address is also
1846 1835 * acceptable.
1847 1836 *
1848 1837 * In the case of a multicast address, however, the
1849 1838 * upper protocol is expected to reset the src address
1850 1839 * to zero when we return IPVL_MCAST so that
1851 1840 * no packets are emitted with multicast address as
1852 1841 * source address.
1853 1842 * The addresses valid for bind are:
1854 1843 * (1) - in6addr_any
1855 1844 * (2) - IP address of an UP interface
1856 1845 * (3) - IP address of a DOWN interface
1857 1846 * (4) - a multicast address. In this case
1858 1847 * the conn will only receive packets destined to
1859 1848 * the specified multicast address. Note: the
1860 1849 * application still has to issue an
1861 1850 * IPV6_JOIN_GROUP socket option.
1862 1851 *
1863 1852 * In all the above cases, the bound address must be valid in the current zone.
1864 1853 * When the address is loopback or multicast, there might be many matching IREs
1865 1854 * so bind has to look up based on the zone.
1866 1855 */
1867 1856 ip_laddr_t
1868 1857 ip_laddr_verify_v6(const in6_addr_t *v6src, zoneid_t zoneid,
1869 1858 ip_stack_t *ipst, boolean_t allow_mcbc, uint_t scopeid)
1870 1859 {
1871 1860 ire_t *src_ire;
1872 1861 uint_t match_flags;
1873 1862 ill_t *ill = NULL;
1874 1863
1875 1864 ASSERT(!IN6_IS_ADDR_V4MAPPED(v6src));
1876 1865 ASSERT(!IN6_IS_ADDR_UNSPECIFIED(v6src));
1877 1866
1878 1867 match_flags = MATCH_IRE_ZONEONLY;
1879 1868 if (scopeid != 0) {
1880 1869 ill = ill_lookup_on_ifindex(scopeid, B_TRUE, ipst);
1881 1870 if (ill == NULL)
1882 1871 return (IPVL_BAD);
1883 1872 match_flags |= MATCH_IRE_ILL;
1884 1873 }
1885 1874
1886 1875 src_ire = ire_ftable_lookup_v6(v6src, NULL, NULL, 0,
1887 1876 ill, zoneid, NULL, match_flags, 0, ipst, NULL);
1888 1877 if (ill != NULL)
1889 1878 ill_refrele(ill);
1890 1879
1891 1880 /*
1892 1881 * If an address other than in6addr_any is requested,
1893 1882 * we verify that it is a valid address for bind
1894 1883 * Note: Following code is in if-else-if form for
1895 1884 * readability compared to a condition check.
1896 1885 */
1897 1886 if (src_ire != NULL && (src_ire->ire_type & (IRE_LOCAL|IRE_LOOPBACK))) {
1898 1887 /*
1899 1888 * (2) Bind to address of local UP interface
1900 1889 */
1901 1890 ire_refrele(src_ire);
1902 1891 return (IPVL_UNICAST_UP);
1903 1892 } else if (IN6_IS_ADDR_MULTICAST(v6src)) {
1904 1893 /* (4) bind to multicast address. */
1905 1894 if (src_ire != NULL)
1906 1895 ire_refrele(src_ire);
1907 1896
1908 1897 /*
1909 1898 * Note: caller should take IPV6_MULTICAST_IF
1910 1899 * into account when selecting a real source address.
1911 1900 */
1912 1901 if (allow_mcbc)
1913 1902 return (IPVL_MCAST);
1914 1903 else
1915 1904 return (IPVL_BAD);
1916 1905 } else {
1917 1906 ipif_t *ipif;
1918 1907
1919 1908 /*
1920 1909 * (3) Bind to address of local DOWN interface?
1921 1910 * (ipif_lookup_addr() looks up all interfaces
1922 1911 * but we do not get here for UP interfaces
1923 1912 * - case (2) above)
1924 1913 */
1925 1914 if (src_ire != NULL)
1926 1915 ire_refrele(src_ire);
1927 1916
1928 1917 ipif = ipif_lookup_addr_v6(v6src, NULL, zoneid, ipst);
1929 1918 if (ipif == NULL)
1930 1919 return (IPVL_BAD);
1931 1920
1932 1921 /* Not a useful source? */
1933 1922 if (ipif->ipif_flags & (IPIF_NOLOCAL | IPIF_ANYCAST)) {
1934 1923 ipif_refrele(ipif);
1935 1924 return (IPVL_BAD);
1936 1925 }
1937 1926 ipif_refrele(ipif);
1938 1927 return (IPVL_UNICAST_DOWN);
1939 1928 }
1940 1929 }
1941 1930
1942 1931 /*
1943 1932 * Verify that both the source and destination addresses are valid. If
1944 1933 * IPDF_VERIFY_DST is not set, then the destination address may be unreachable,
1945 1934 * i.e. have no route to it. Protocols like TCP want to verify destination
1946 1935 * reachability, while tunnels do not.
1947 1936 *
1948 1937 * Determine the route, the interface, and (optionally) the source address
1949 1938 * to use to reach a given destination.
1950 1939 * Note that we allow connect to broadcast and multicast addresses when
1951 1940 * IPDF_ALLOW_MCBC is set.
1952 1941 * first_hop and dst_addr are normally the same, but if source routing
1953 1942 * they will differ; in that case the first_hop is what we'll use for the
1954 1943 * routing lookup but the dce and label checks will be done on dst_addr,
1955 1944 *
1956 1945 * If uinfo is set, then we fill in the best available information
1957 1946 * we have for the destination. This is based on (in priority order) any
1958 1947 * metrics and path MTU stored in a dce_t, route metrics, and finally the
1959 1948 * ill_mtu/ill_mc_mtu.
1960 1949 *
1961 1950 * Tsol note: If we have a source route then dst_addr != firsthop. But we
1962 1951 * always do the label check on dst_addr.
1963 1952 *
1964 1953 * Assumes that the caller has set ixa_scopeid for link-local communication.
1965 1954 */
1966 1955 int
1967 1956 ip_set_destination_v6(in6_addr_t *src_addrp, const in6_addr_t *dst_addr,
1968 1957 const in6_addr_t *firsthop, ip_xmit_attr_t *ixa, iulp_t *uinfo,
1969 1958 uint32_t flags, uint_t mac_mode)
1970 1959 {
1971 1960 ire_t *ire;
1972 1961 int error = 0;
1973 1962 in6_addr_t setsrc; /* RTF_SETSRC */
1974 1963 zoneid_t zoneid = ixa->ixa_zoneid; /* Honors SO_ALLZONES */
1975 1964 ip_stack_t *ipst = ixa->ixa_ipst;
1976 1965 dce_t *dce;
1977 1966 uint_t pmtu;
1978 1967 uint_t ifindex;
1979 1968 uint_t generation;
1980 1969 nce_t *nce;
1981 1970 ill_t *ill = NULL;
1982 1971 boolean_t multirt = B_FALSE;
1983 1972
1984 1973 ASSERT(!IN6_IS_ADDR_V4MAPPED(dst_addr));
1985 1974
1986 1975 ASSERT(!(ixa->ixa_flags & IXAF_IS_IPV4));
1987 1976
1988 1977 /*
1989 1978 * We never send to zero; the ULPs map it to the loopback address.
1990 1979 * We can't allow it since we use zero to mean unitialized in some
1991 1980 * places.
1992 1981 */
1993 1982 ASSERT(!IN6_IS_ADDR_UNSPECIFIED(dst_addr));
1994 1983
1995 1984 if (is_system_labeled()) {
1996 1985 ts_label_t *tsl = NULL;
1997 1986
1998 1987 error = tsol_check_dest(ixa->ixa_tsl, dst_addr, IPV6_VERSION,
1999 1988 mac_mode, (flags & IPDF_ZONE_IS_GLOBAL) != 0, &tsl);
2000 1989 if (error != 0)
2001 1990 return (error);
2002 1991 if (tsl != NULL) {
2003 1992 /* Update the label */
2004 1993 ip_xmit_attr_replace_tsl(ixa, tsl);
2005 1994 }
2006 1995 }
2007 1996
2008 1997 setsrc = ipv6_all_zeros;
2009 1998 /*
2010 1999 * Select a route; For IPMP interfaces, we would only select
2011 2000 * a "hidden" route (i.e., going through a specific under_ill)
2012 2001 * if ixa_ifindex has been specified.
2013 2002 */
2014 2003 ire = ip_select_route_v6(firsthop, *src_addrp, ixa, &generation,
2015 2004 &setsrc, &error, &multirt);
2016 2005 ASSERT(ire != NULL); /* IRE_NOROUTE if none found */
2017 2006 if (error != 0)
2018 2007 goto bad_addr;
2019 2008
2020 2009 /*
2021 2010 * ire can't be a broadcast or multicast unless IPDF_ALLOW_MCBC is set.
2022 2011 * If IPDF_VERIFY_DST is set, the destination must be reachable.
2023 2012 * Otherwise the destination needn't be reachable.
2024 2013 *
2025 2014 * If we match on a reject or black hole, then we've got a
2026 2015 * local failure. May as well fail out the connect() attempt,
2027 2016 * since it's never going to succeed.
2028 2017 */
2029 2018 if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
2030 2019 /*
2031 2020 * If we're verifying destination reachability, we always want
2032 2021 * to complain here.
2033 2022 *
2034 2023 * If we're not verifying destination reachability but the
2035 2024 * destination has a route, we still want to fail on the
2036 2025 * temporary address and broadcast address tests.
2037 2026 *
2038 2027 * In both cases do we let the code continue so some reasonable
2039 2028 * information is returned to the caller. That enables the
2040 2029 * caller to use (and even cache) the IRE. conn_ip_ouput will
2041 2030 * use the generation mismatch path to check for the unreachable
2042 2031 * case thereby avoiding any specific check in the main path.
2043 2032 */
2044 2033 ASSERT(generation == IRE_GENERATION_VERIFY);
2045 2034 if (flags & IPDF_VERIFY_DST) {
2046 2035 /*
2047 2036 * Set errno but continue to set up ixa_ire to be
2048 2037 * the RTF_REJECT|RTF_BLACKHOLE IRE.
2049 2038 * That allows callers to use ip_output to get an
2050 2039 * ICMP error back.
2051 2040 */
2052 2041 if (!(ire->ire_type & IRE_HOST))
2053 2042 error = ENETUNREACH;
2054 2043 else
2055 2044 error = EHOSTUNREACH;
2056 2045 }
2057 2046 }
2058 2047
2059 2048 if ((ire->ire_type & (IRE_BROADCAST|IRE_MULTICAST)) &&
2060 2049 !(flags & IPDF_ALLOW_MCBC)) {
2061 2050 ire_refrele(ire);
2062 2051 ire = ire_reject(ipst, B_FALSE);
2063 2052 generation = IRE_GENERATION_VERIFY;
2064 2053 error = ENETUNREACH;
2065 2054 }
2066 2055
2067 2056 /* Cache things */
2068 2057 if (ixa->ixa_ire != NULL)
2069 2058 ire_refrele_notr(ixa->ixa_ire);
2070 2059 #ifdef DEBUG
2071 2060 ire_refhold_notr(ire);
2072 2061 ire_refrele(ire);
2073 2062 #endif
2074 2063 ixa->ixa_ire = ire;
2075 2064 ixa->ixa_ire_generation = generation;
2076 2065
2077 2066 /*
2078 2067 * Ensure that ixa_dce is always set any time that ixa_ire is set,
2079 2068 * since some callers will send a packet to conn_ip_output() even if
2080 2069 * there's an error.
2081 2070 */
2082 2071 ifindex = 0;
2083 2072 if (IN6_IS_ADDR_LINKSCOPE(dst_addr)) {
2084 2073 /* If we are creating a DCE we'd better have an ifindex */
2085 2074 if (ill != NULL)
2086 2075 ifindex = ill->ill_phyint->phyint_ifindex;
2087 2076 else
2088 2077 flags &= ~IPDF_UNIQUE_DCE;
2089 2078 }
2090 2079
2091 2080 if (flags & IPDF_UNIQUE_DCE) {
2092 2081 /* Fallback to the default dce if allocation fails */
2093 2082 dce = dce_lookup_and_add_v6(dst_addr, ifindex, ipst);
2094 2083 if (dce != NULL) {
2095 2084 generation = dce->dce_generation;
2096 2085 } else {
2097 2086 dce = dce_lookup_v6(dst_addr, ifindex, ipst,
2098 2087 &generation);
2099 2088 }
2100 2089 } else {
2101 2090 dce = dce_lookup_v6(dst_addr, ifindex, ipst, &generation);
2102 2091 }
2103 2092 ASSERT(dce != NULL);
2104 2093 if (ixa->ixa_dce != NULL)
2105 2094 dce_refrele_notr(ixa->ixa_dce);
2106 2095 #ifdef DEBUG
2107 2096 dce_refhold_notr(dce);
2108 2097 dce_refrele(dce);
2109 2098 #endif
2110 2099 ixa->ixa_dce = dce;
2111 2100 ixa->ixa_dce_generation = generation;
2112 2101
2113 2102
2114 2103 /*
2115 2104 * For multicast with multirt we have a flag passed back from
2116 2105 * ire_lookup_multi_ill_v6 since we don't have an IRE for each
2117 2106 * possible multicast address.
2118 2107 * We also need a flag for multicast since we can't check
2119 2108 * whether RTF_MULTIRT is set in ixa_ire for multicast.
2120 2109 */
2121 2110 if (multirt) {
2122 2111 ixa->ixa_postfragfn = ip_postfrag_multirt_v6;
2123 2112 ixa->ixa_flags |= IXAF_MULTIRT_MULTICAST;
2124 2113 } else {
2125 2114 ixa->ixa_postfragfn = ire->ire_postfragfn;
2126 2115 ixa->ixa_flags &= ~IXAF_MULTIRT_MULTICAST;
2127 2116 }
2128 2117 if (!(ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE))) {
2129 2118 /* Get an nce to cache. */
2130 2119 nce = ire_to_nce(ire, NULL, firsthop);
2131 2120 if (nce == NULL) {
2132 2121 /* Allocation failure? */
2133 2122 ixa->ixa_ire_generation = IRE_GENERATION_VERIFY;
2134 2123 } else {
2135 2124 if (ixa->ixa_nce != NULL)
2136 2125 nce_refrele(ixa->ixa_nce);
2137 2126 ixa->ixa_nce = nce;
2138 2127 }
2139 2128 }
2140 2129
2141 2130 /*
2142 2131 * If the source address is a loopback address, the
2143 2132 * destination had best be local or multicast.
2144 2133 * If we are sending to an IRE_LOCAL using a loopback source then
2145 2134 * it had better be the same zoneid.
2146 2135 */
2147 2136 if (IN6_IS_ADDR_LOOPBACK(src_addrp)) {
2148 2137 if ((ire->ire_type & IRE_LOCAL) && ire->ire_zoneid != zoneid) {
2149 2138 ire = NULL; /* Stored in ixa_ire */
2150 2139 error = EADDRNOTAVAIL;
2151 2140 goto bad_addr;
2152 2141 }
2153 2142 if (!(ire->ire_type & (IRE_LOOPBACK|IRE_LOCAL|IRE_MULTICAST))) {
2154 2143 ire = NULL; /* Stored in ixa_ire */
2155 2144 error = EADDRNOTAVAIL;
2156 2145 goto bad_addr;
2157 2146 }
2158 2147 }
2159 2148
2160 2149 /*
2161 2150 * Does the caller want us to pick a source address?
2162 2151 */
2163 2152 if (flags & IPDF_SELECT_SRC) {
2164 2153 in6_addr_t src_addr;
2165 2154
2166 2155 /*
2167 2156 * We use use ire_nexthop_ill to avoid the under ipmp
2168 2157 * interface for source address selection. Note that for ipmp
2169 2158 * probe packets, ixa_ifindex would have been specified, and
2170 2159 * the ip_select_route() invocation would have picked an ire
2171 2160 * will ire_ill pointing at an under interface.
2172 2161 */
2173 2162 ill = ire_nexthop_ill(ire);
2174 2163
2175 2164 /* If unreachable we have no ill but need some source */
2176 2165 if (ill == NULL) {
2177 2166 src_addr = ipv6_loopback;
2178 2167 /* Make sure we look for a better source address */
2179 2168 generation = SRC_GENERATION_VERIFY;
2180 2169 } else {
2181 2170 error = ip_select_source_v6(ill, &setsrc, dst_addr,
2182 2171 zoneid, ipst, B_FALSE, ixa->ixa_src_preferences,
2183 2172 &src_addr, &generation, NULL);
2184 2173 if (error != 0) {
2185 2174 ire = NULL; /* Stored in ixa_ire */
2186 2175 goto bad_addr;
2187 2176 }
2188 2177 }
2189 2178
2190 2179 /*
2191 2180 * We allow the source address to to down.
2192 2181 * However, we check that we don't use the loopback address
2193 2182 * as a source when sending out on the wire.
2194 2183 */
2195 2184 if (IN6_IS_ADDR_LOOPBACK(&src_addr) &&
2196 2185 !(ire->ire_type & (IRE_LOCAL|IRE_LOOPBACK|IRE_MULTICAST)) &&
2197 2186 !(ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE))) {
2198 2187 ire = NULL; /* Stored in ixa_ire */
2199 2188 error = EADDRNOTAVAIL;
2200 2189 goto bad_addr;
2201 2190 }
2202 2191
2203 2192 *src_addrp = src_addr;
2204 2193 ixa->ixa_src_generation = generation;
2205 2194 }
2206 2195
2207 2196 /*
2208 2197 * Make sure we don't leave an unreachable ixa_nce in place
2209 2198 * since ip_select_route is used when we unplumb i.e., remove
2210 2199 * references on ixa_ire, ixa_nce, and ixa_dce.
2211 2200 */
2212 2201 nce = ixa->ixa_nce;
2213 2202 if (nce != NULL && nce->nce_is_condemned) {
2214 2203 nce_refrele(nce);
2215 2204 ixa->ixa_nce = NULL;
2216 2205 ixa->ixa_ire_generation = IRE_GENERATION_VERIFY;
2217 2206 }
2218 2207
2219 2208 /*
2220 2209 * Note that IPv6 multicast supports PMTU discovery unlike IPv4
2221 2210 * multicast. But pmtu discovery is only enabled for connected
2222 2211 * sockets in general.
2223 2212 */
2224 2213
2225 2214 /*
2226 2215 * Set initial value for fragmentation limit. Either conn_ip_output
2227 2216 * or ULP might updates it when there are routing changes.
2228 2217 * Handles a NULL ixa_ire->ire_ill or a NULL ixa_nce for RTF_REJECT.
2229 2218 */
2230 2219 pmtu = ip_get_pmtu(ixa);
2231 2220 ixa->ixa_fragsize = pmtu;
2232 2221 /* Make sure ixa_fragsize and ixa_pmtu remain identical */
2233 2222 if (ixa->ixa_flags & IXAF_VERIFY_PMTU)
2234 2223 ixa->ixa_pmtu = pmtu;
2235 2224
2236 2225 /*
2237 2226 * Extract information useful for some transports.
2238 2227 * First we look for DCE metrics. Then we take what we have in
2239 2228 * the metrics in the route, where the offlink is used if we have
2240 2229 * one.
2241 2230 */
2242 2231 if (uinfo != NULL) {
2243 2232 bzero(uinfo, sizeof (*uinfo));
2244 2233
2245 2234 if (dce->dce_flags & DCEF_UINFO)
2246 2235 *uinfo = dce->dce_uinfo;
2247 2236
2248 2237 rts_merge_metrics(uinfo, &ire->ire_metrics);
2249 2238
2250 2239 /* Allow ire_metrics to decrease the path MTU from above */
2251 2240 if (uinfo->iulp_mtu == 0 || uinfo->iulp_mtu > pmtu)
2252 2241 uinfo->iulp_mtu = pmtu;
2253 2242
2254 2243 uinfo->iulp_localnet = (ire->ire_type & IRE_ONLINK) != 0;
2255 2244 uinfo->iulp_loopback = (ire->ire_type & IRE_LOOPBACK) != 0;
2256 2245 uinfo->iulp_local = (ire->ire_type & IRE_LOCAL) != 0;
2257 2246 }
2258 2247
2259 2248 if (ill != NULL)
2260 2249 ill_refrele(ill);
2261 2250
2262 2251 return (error);
2263 2252
2264 2253 bad_addr:
2265 2254 if (ire != NULL)
2266 2255 ire_refrele(ire);
2267 2256
2268 2257 if (ill != NULL)
2269 2258 ill_refrele(ill);
2270 2259
2271 2260 /*
2272 2261 * Make sure we don't leave an unreachable ixa_nce in place
2273 2262 * since ip_select_route is used when we unplumb i.e., remove
2274 2263 * references on ixa_ire, ixa_nce, and ixa_dce.
2275 2264 */
2276 2265 nce = ixa->ixa_nce;
2277 2266 if (nce != NULL && nce->nce_is_condemned) {
2278 2267 nce_refrele(nce);
2279 2268 ixa->ixa_nce = NULL;
2280 2269 ixa->ixa_ire_generation = IRE_GENERATION_VERIFY;
2281 2270 }
2282 2271
2283 2272 return (error);
2284 2273 }
2285 2274
2286 2275 /*
2287 2276 * Handle protocols with which IP is less intimate. There
2288 2277 * can be more than one stream bound to a particular
2289 2278 * protocol. When this is the case, normally each one gets a copy
2290 2279 * of any incoming packets.
2291 2280 *
2292 2281 * Zones notes:
2293 2282 * Packets will be distributed to conns in all zones. This is really only
2294 2283 * useful for ICMPv6 as only applications in the global zone can create raw
2295 2284 * sockets for other protocols.
2296 2285 */
2297 2286 void
2298 2287 ip_fanout_proto_v6(mblk_t *mp, ip6_t *ip6h, ip_recv_attr_t *ira)
2299 2288 {
2300 2289 mblk_t *mp1;
2301 2290 in6_addr_t laddr = ip6h->ip6_dst;
2302 2291 conn_t *connp, *first_connp, *next_connp;
2303 2292 connf_t *connfp;
2304 2293 ill_t *ill = ira->ira_ill;
2305 2294 ip_stack_t *ipst = ill->ill_ipst;
2306 2295
2307 2296 connfp = &ipst->ips_ipcl_proto_fanout_v6[ira->ira_protocol];
2308 2297 mutex_enter(&connfp->connf_lock);
2309 2298 connp = connfp->connf_head;
2310 2299 for (connp = connfp->connf_head; connp != NULL;
2311 2300 connp = connp->conn_next) {
2312 2301 /* Note: IPCL_PROTO_MATCH_V6 includes conn_wantpacket */
2313 2302 if (IPCL_PROTO_MATCH_V6(connp, ira, ip6h) &&
2314 2303 (!(ira->ira_flags & IRAF_SYSTEM_LABELED) ||
2315 2304 tsol_receive_local(mp, &laddr, IPV6_VERSION, ira, connp)))
2316 2305 break;
2317 2306 }
2318 2307
2319 2308 if (connp == NULL) {
2320 2309 /*
2321 2310 * No one bound to this port. Is
2322 2311 * there a client that wants all
2323 2312 * unclaimed datagrams?
2324 2313 */
2325 2314 mutex_exit(&connfp->connf_lock);
2326 2315 ip_fanout_send_icmp_v6(mp, ICMP6_PARAM_PROB,
2327 2316 ICMP6_PARAMPROB_NEXTHEADER, ira);
2328 2317 return;
2329 2318 }
2330 2319
2331 2320 ASSERT(IPCL_IS_NONSTR(connp) || connp->conn_rq != NULL);
2332 2321
2333 2322 CONN_INC_REF(connp);
2334 2323 first_connp = connp;
2335 2324
2336 2325 /*
2337 2326 * XXX: Fix the multiple protocol listeners case. We should not
2338 2327 * be walking the conn->conn_next list here.
2339 2328 */
2340 2329 connp = connp->conn_next;
2341 2330 for (;;) {
2342 2331 while (connp != NULL) {
2343 2332 /* Note: IPCL_PROTO_MATCH_V6 includes conn_wantpacket */
2344 2333 if (IPCL_PROTO_MATCH_V6(connp, ira, ip6h) &&
2345 2334 (!(ira->ira_flags & IRAF_SYSTEM_LABELED) ||
2346 2335 tsol_receive_local(mp, &laddr, IPV6_VERSION,
2347 2336 ira, connp)))
2348 2337 break;
2349 2338 connp = connp->conn_next;
2350 2339 }
2351 2340
2352 2341 if (connp == NULL) {
2353 2342 /* No more interested clients */
2354 2343 connp = first_connp;
2355 2344 break;
2356 2345 }
2357 2346 if (((mp1 = dupmsg(mp)) == NULL) &&
2358 2347 ((mp1 = copymsg(mp)) == NULL)) {
2359 2348 /* Memory allocation failed */
2360 2349 BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards);
2361 2350 ip_drop_input("ipIfStatsInDiscards", mp, ill);
2362 2351 connp = first_connp;
2363 2352 break;
2364 2353 }
2365 2354
2366 2355 CONN_INC_REF(connp);
2367 2356 mutex_exit(&connfp->connf_lock);
2368 2357
2369 2358 ip_fanout_proto_conn(connp, mp1, NULL, (ip6_t *)mp1->b_rptr,
2370 2359 ira);
2371 2360
2372 2361 mutex_enter(&connfp->connf_lock);
2373 2362 /* Follow the next pointer before releasing the conn. */
2374 2363 next_connp = connp->conn_next;
2375 2364 CONN_DEC_REF(connp);
2376 2365 connp = next_connp;
2377 2366 }
2378 2367
2379 2368 /* Last one. Send it upstream. */
2380 2369 mutex_exit(&connfp->connf_lock);
2381 2370
2382 2371 ip_fanout_proto_conn(connp, mp, NULL, ip6h, ira);
2383 2372
2384 2373 CONN_DEC_REF(connp);
2385 2374 }
2386 2375
2387 2376 /*
2388 2377 * Called when it is conceptually a ULP that would sent the packet
2389 2378 * e.g., port unreachable and nexthdr unknown. Check that the packet
2390 2379 * would have passed the IPsec global policy before sending the error.
2391 2380 *
2392 2381 * Send an ICMP error after patching up the packet appropriately.
2393 2382 * Uses ip_drop_input and bumps the appropriate MIB.
2394 2383 * For ICMP6_PARAMPROB_NEXTHEADER we determine the offset to use.
2395 2384 */
2396 2385 void
2397 2386 ip_fanout_send_icmp_v6(mblk_t *mp, uint_t icmp_type, uint8_t icmp_code,
2398 2387 ip_recv_attr_t *ira)
2399 2388 {
2400 2389 ip6_t *ip6h;
2401 2390 boolean_t secure;
2402 2391 ill_t *ill = ira->ira_ill;
2403 2392 ip_stack_t *ipst = ill->ill_ipst;
2404 2393 netstack_t *ns = ipst->ips_netstack;
2405 2394 ipsec_stack_t *ipss = ns->netstack_ipsec;
2406 2395
2407 2396 secure = ira->ira_flags & IRAF_IPSEC_SECURE;
2408 2397
2409 2398 /*
2410 2399 * We are generating an icmp error for some inbound packet.
2411 2400 * Called from all ip_fanout_(udp, tcp, proto) functions.
2412 2401 * Before we generate an error, check with global policy
2413 2402 * to see whether this is allowed to enter the system. As
2414 2403 * there is no "conn", we are checking with global policy.
2415 2404 */
2416 2405 ip6h = (ip6_t *)mp->b_rptr;
2417 2406 if (secure || ipss->ipsec_inbound_v6_policy_present) {
2418 2407 mp = ipsec_check_global_policy(mp, NULL, NULL, ip6h, ira, ns);
2419 2408 if (mp == NULL)
2420 2409 return;
2421 2410 }
2422 2411
2423 2412 /* We never send errors for protocols that we do implement */
2424 2413 if (ira->ira_protocol == IPPROTO_ICMPV6) {
2425 2414 BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards);
2426 2415 ip_drop_input("ip_fanout_send_icmp_v6", mp, ill);
2427 2416 freemsg(mp);
2428 2417 return;
2429 2418 }
2430 2419
2431 2420 switch (icmp_type) {
2432 2421 case ICMP6_DST_UNREACH:
2433 2422 ASSERT(icmp_code == ICMP6_DST_UNREACH_NOPORT);
2434 2423
2435 2424 BUMP_MIB(ill->ill_ip_mib, udpIfStatsNoPorts);
2436 2425 ip_drop_input("ipIfStatsNoPorts", mp, ill);
2437 2426
2438 2427 icmp_unreachable_v6(mp, icmp_code, B_FALSE, ira);
2439 2428 break;
2440 2429 case ICMP6_PARAM_PROB:
2441 2430 ASSERT(icmp_code == ICMP6_PARAMPROB_NEXTHEADER);
2442 2431
2443 2432 BUMP_MIB(ill->ill_ip_mib, ipIfStatsInUnknownProtos);
2444 2433 ip_drop_input("ipIfStatsInUnknownProtos", mp, ill);
2445 2434
2446 2435 /* Let the system determine the offset for this one */
2447 2436 icmp_param_problem_nexthdr_v6(mp, B_FALSE, ira);
2448 2437 break;
2449 2438 default:
2450 2439 #ifdef DEBUG
2451 2440 panic("ip_fanout_send_icmp_v6: wrong type");
2452 2441 /*NOTREACHED*/
2453 2442 #else
2454 2443 freemsg(mp);
2455 2444 break;
2456 2445 #endif
2457 2446 }
2458 2447 }
2459 2448
2460 2449 /*
2461 2450 * Fanout for UDP packets that are multicast or ICMP errors.
2462 2451 * (Unicast fanout is handled in ip_input_v6.)
2463 2452 *
2464 2453 * If SO_REUSEADDR is set all multicast packets
2465 2454 * will be delivered to all conns bound to the same port.
2466 2455 *
2467 2456 * Fanout for UDP packets.
2468 2457 * The caller puts <fport, lport> in the ports parameter.
2469 2458 * ire_type must be IRE_BROADCAST for multicast and broadcast packets.
2470 2459 *
2471 2460 * If SO_REUSEADDR is set all multicast and broadcast packets
2472 2461 * will be delivered to all conns bound to the same port.
2473 2462 *
2474 2463 * Zones notes:
2475 2464 * Earlier in ip_input on a system with multiple shared-IP zones we
2476 2465 * duplicate the multicast and broadcast packets and send them up
2477 2466 * with each explicit zoneid that exists on that ill.
2478 2467 * This means that here we can match the zoneid with SO_ALLZONES being special.
2479 2468 */
2480 2469 void
2481 2470 ip_fanout_udp_multi_v6(mblk_t *mp, ip6_t *ip6h, uint16_t lport, uint16_t fport,
2482 2471 ip_recv_attr_t *ira)
2483 2472 {
2484 2473 in6_addr_t laddr;
2485 2474 conn_t *connp;
2486 2475 connf_t *connfp;
2487 2476 in6_addr_t faddr;
2488 2477 ill_t *ill = ira->ira_ill;
2489 2478 ip_stack_t *ipst = ill->ill_ipst;
2490 2479
2491 2480 ASSERT(ira->ira_flags & (IRAF_MULTIBROADCAST|IRAF_ICMP_ERROR));
2492 2481
2493 2482 laddr = ip6h->ip6_dst;
2494 2483 faddr = ip6h->ip6_src;
2495 2484
2496 2485 /* Attempt to find a client stream based on destination port. */
2497 2486 connfp = &ipst->ips_ipcl_udp_fanout[IPCL_UDP_HASH(lport, ipst)];
2498 2487 mutex_enter(&connfp->connf_lock);
2499 2488 connp = connfp->connf_head;
2500 2489 while (connp != NULL) {
2501 2490 if ((IPCL_UDP_MATCH_V6(connp, lport, laddr, fport, faddr)) &&
2502 2491 conn_wantpacket_v6(connp, ira, ip6h) &&
2503 2492 (!(ira->ira_flags & IRAF_SYSTEM_LABELED) ||
2504 2493 tsol_receive_local(mp, &laddr, IPV6_VERSION, ira, connp)))
2505 2494 break;
2506 2495 connp = connp->conn_next;
2507 2496 }
2508 2497
2509 2498 if (connp == NULL)
2510 2499 goto notfound;
2511 2500
2512 2501 CONN_INC_REF(connp);
2513 2502
2514 2503 if (connp->conn_reuseaddr) {
2515 2504 conn_t *first_connp = connp;
2516 2505 conn_t *next_connp;
2517 2506 mblk_t *mp1;
2518 2507
2519 2508 connp = connp->conn_next;
2520 2509 for (;;) {
2521 2510 while (connp != NULL) {
2522 2511 if (IPCL_UDP_MATCH_V6(connp, lport, laddr,
2523 2512 fport, faddr) &&
2524 2513 conn_wantpacket_v6(connp, ira, ip6h) &&
2525 2514 (!(ira->ira_flags & IRAF_SYSTEM_LABELED) ||
2526 2515 tsol_receive_local(mp, &laddr, IPV6_VERSION,
2527 2516 ira, connp)))
2528 2517 break;
2529 2518 connp = connp->conn_next;
2530 2519 }
2531 2520 if (connp == NULL) {
2532 2521 /* No more interested clients */
2533 2522 connp = first_connp;
2534 2523 break;
2535 2524 }
2536 2525 if (((mp1 = dupmsg(mp)) == NULL) &&
2537 2526 ((mp1 = copymsg(mp)) == NULL)) {
2538 2527 /* Memory allocation failed */
2539 2528 BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards);
2540 2529 ip_drop_input("ipIfStatsInDiscards", mp, ill);
2541 2530 connp = first_connp;
2542 2531 break;
2543 2532 }
2544 2533
2545 2534 CONN_INC_REF(connp);
2546 2535 mutex_exit(&connfp->connf_lock);
2547 2536
2548 2537 IP6_STAT(ipst, ip6_udp_fanmb);
2549 2538 ip_fanout_udp_conn(connp, mp1, NULL,
2550 2539 (ip6_t *)mp1->b_rptr, ira);
2551 2540
2552 2541 mutex_enter(&connfp->connf_lock);
2553 2542 /* Follow the next pointer before releasing the conn. */
2554 2543 next_connp = connp->conn_next;
2555 2544 IP6_STAT(ipst, ip6_udp_fanmb);
2556 2545 CONN_DEC_REF(connp);
2557 2546 connp = next_connp;
2558 2547 }
2559 2548 }
2560 2549
2561 2550 /* Last one. Send it upstream. */
2562 2551 mutex_exit(&connfp->connf_lock);
2563 2552
2564 2553 IP6_STAT(ipst, ip6_udp_fanmb);
2565 2554 ip_fanout_udp_conn(connp, mp, NULL, ip6h, ira);
2566 2555 CONN_DEC_REF(connp);
2567 2556 return;
2568 2557
2569 2558 notfound:
2570 2559 mutex_exit(&connfp->connf_lock);
2571 2560 /*
2572 2561 * No one bound to this port. Is
2573 2562 * there a client that wants all
2574 2563 * unclaimed datagrams?
2575 2564 */
2576 2565 if (ipst->ips_ipcl_proto_fanout_v6[IPPROTO_UDP].connf_head != NULL) {
2577 2566 ASSERT(ira->ira_protocol == IPPROTO_UDP);
2578 2567 ip_fanout_proto_v6(mp, ip6h, ira);
2579 2568 } else {
2580 2569 ip_fanout_send_icmp_v6(mp, ICMP6_DST_UNREACH,
2581 2570 ICMP6_DST_UNREACH_NOPORT, ira);
2582 2571 }
2583 2572 }
2584 2573
2585 2574 /*
2586 2575 * int ip_find_hdr_v6()
2587 2576 *
2588 2577 * This routine is used by the upper layer protocols, iptun, and IPsec:
2589 2578 * - Set extension header pointers to appropriate locations
2590 2579 * - Determine IPv6 header length and return it
2591 2580 * - Return a pointer to the last nexthdr value
2592 2581 *
2593 2582 * The caller must initialize ipp_fields.
2594 2583 * The upper layer protocols normally set label_separate which makes the
2595 2584 * routine put the TX label in ipp_label_v6. If this is not set then
2596 2585 * the hop-by-hop options including the label are placed in ipp_hopopts.
2597 2586 *
2598 2587 * NOTE: If multiple extension headers of the same type are present,
2599 2588 * ip_find_hdr_v6() will set the respective extension header pointers
2600 2589 * to the first one that it encounters in the IPv6 header. It also
2601 2590 * skips fragment headers. This routine deals with malformed packets
2602 2591 * of various sorts in which case the returned length is up to the
2603 2592 * malformed part.
2604 2593 */
2605 2594 int
2606 2595 ip_find_hdr_v6(mblk_t *mp, ip6_t *ip6h, boolean_t label_separate, ip_pkt_t *ipp,
2607 2596 uint8_t *nexthdrp)
2608 2597 {
2609 2598 uint_t length, ehdrlen;
2610 2599 uint8_t nexthdr;
2611 2600 uint8_t *whereptr, *endptr;
2612 2601 ip6_dest_t *tmpdstopts;
2613 2602 ip6_rthdr_t *tmprthdr;
2614 2603 ip6_hbh_t *tmphopopts;
2615 2604 ip6_frag_t *tmpfraghdr;
2616 2605
2617 2606 ipp->ipp_fields |= IPPF_HOPLIMIT | IPPF_TCLASS | IPPF_ADDR;
2618 2607 ipp->ipp_hoplimit = ip6h->ip6_hops;
2619 2608 ipp->ipp_tclass = IPV6_FLOW_TCLASS(ip6h->ip6_flow);
2620 2609 ipp->ipp_addr = ip6h->ip6_dst;
2621 2610
2622 2611 length = IPV6_HDR_LEN;
2623 2612 whereptr = ((uint8_t *)&ip6h[1]); /* point to next hdr */
2624 2613 endptr = mp->b_wptr;
2625 2614
2626 2615 nexthdr = ip6h->ip6_nxt;
2627 2616 while (whereptr < endptr) {
2628 2617 /* Is there enough left for len + nexthdr? */
2629 2618 if (whereptr + MIN_EHDR_LEN > endptr)
2630 2619 goto done;
2631 2620
2632 2621 switch (nexthdr) {
2633 2622 case IPPROTO_HOPOPTS: {
2634 2623 /* We check for any CIPSO */
2635 2624 uchar_t *secopt;
2636 2625 boolean_t hbh_needed;
2637 2626 uchar_t *after_secopt;
2638 2627
2639 2628 tmphopopts = (ip6_hbh_t *)whereptr;
2640 2629 ehdrlen = 8 * (tmphopopts->ip6h_len + 1);
2641 2630 if ((uchar_t *)tmphopopts + ehdrlen > endptr)
2642 2631 goto done;
2643 2632 nexthdr = tmphopopts->ip6h_nxt;
2644 2633
2645 2634 if (!label_separate) {
2646 2635 secopt = NULL;
2647 2636 after_secopt = whereptr;
2648 2637 } else {
2649 2638 /*
2650 2639 * We have dropped packets with bad options in
2651 2640 * ip6_input. No need to check return value
2652 2641 * here.
2653 2642 */
2654 2643 (void) tsol_find_secopt_v6(whereptr, ehdrlen,
2655 2644 &secopt, &after_secopt, &hbh_needed);
2656 2645 }
2657 2646 if (secopt != NULL && after_secopt - whereptr > 0) {
2658 2647 ipp->ipp_fields |= IPPF_LABEL_V6;
2659 2648 ipp->ipp_label_v6 = secopt;
2660 2649 ipp->ipp_label_len_v6 = after_secopt - whereptr;
2661 2650 } else {
2662 2651 ipp->ipp_label_len_v6 = 0;
2663 2652 after_secopt = whereptr;
2664 2653 hbh_needed = B_TRUE;
2665 2654 }
2666 2655 /* return only 1st hbh */
2667 2656 if (hbh_needed && !(ipp->ipp_fields & IPPF_HOPOPTS)) {
2668 2657 ipp->ipp_fields |= IPPF_HOPOPTS;
2669 2658 ipp->ipp_hopopts = (ip6_hbh_t *)after_secopt;
2670 2659 ipp->ipp_hopoptslen = ehdrlen -
2671 2660 ipp->ipp_label_len_v6;
2672 2661 }
2673 2662 break;
2674 2663 }
2675 2664 case IPPROTO_DSTOPTS:
2676 2665 tmpdstopts = (ip6_dest_t *)whereptr;
2677 2666 ehdrlen = 8 * (tmpdstopts->ip6d_len + 1);
2678 2667 if ((uchar_t *)tmpdstopts + ehdrlen > endptr)
2679 2668 goto done;
2680 2669 nexthdr = tmpdstopts->ip6d_nxt;
2681 2670 /*
2682 2671 * ipp_dstopts is set to the destination header after a
2683 2672 * routing header.
2684 2673 * Assume it is a post-rthdr destination header
2685 2674 * and adjust when we find an rthdr.
2686 2675 */
2687 2676 if (!(ipp->ipp_fields & IPPF_DSTOPTS)) {
2688 2677 ipp->ipp_fields |= IPPF_DSTOPTS;
2689 2678 ipp->ipp_dstopts = tmpdstopts;
2690 2679 ipp->ipp_dstoptslen = ehdrlen;
2691 2680 }
2692 2681 break;
2693 2682 case IPPROTO_ROUTING:
2694 2683 tmprthdr = (ip6_rthdr_t *)whereptr;
2695 2684 ehdrlen = 8 * (tmprthdr->ip6r_len + 1);
2696 2685 if ((uchar_t *)tmprthdr + ehdrlen > endptr)
2697 2686 goto done;
2698 2687 nexthdr = tmprthdr->ip6r_nxt;
2699 2688 /* return only 1st rthdr */
2700 2689 if (!(ipp->ipp_fields & IPPF_RTHDR)) {
2701 2690 ipp->ipp_fields |= IPPF_RTHDR;
2702 2691 ipp->ipp_rthdr = tmprthdr;
2703 2692 ipp->ipp_rthdrlen = ehdrlen;
2704 2693 }
2705 2694 /*
2706 2695 * Make any destination header we've seen be a
2707 2696 * pre-rthdr destination header.
2708 2697 */
2709 2698 if (ipp->ipp_fields & IPPF_DSTOPTS) {
2710 2699 ipp->ipp_fields &= ~IPPF_DSTOPTS;
2711 2700 ipp->ipp_fields |= IPPF_RTHDRDSTOPTS;
2712 2701 ipp->ipp_rthdrdstopts = ipp->ipp_dstopts;
2713 2702 ipp->ipp_dstopts = NULL;
2714 2703 ipp->ipp_rthdrdstoptslen = ipp->ipp_dstoptslen;
2715 2704 ipp->ipp_dstoptslen = 0;
2716 2705 }
2717 2706 break;
2718 2707 case IPPROTO_FRAGMENT:
2719 2708 tmpfraghdr = (ip6_frag_t *)whereptr;
2720 2709 ehdrlen = sizeof (ip6_frag_t);
2721 2710 if ((uchar_t *)tmpfraghdr + ehdrlen > endptr)
2722 2711 goto done;
2723 2712 nexthdr = tmpfraghdr->ip6f_nxt;
2724 2713 if (!(ipp->ipp_fields & IPPF_FRAGHDR)) {
2725 2714 ipp->ipp_fields |= IPPF_FRAGHDR;
2726 2715 ipp->ipp_fraghdr = tmpfraghdr;
2727 2716 ipp->ipp_fraghdrlen = ehdrlen;
2728 2717 }
2729 2718 break;
2730 2719 case IPPROTO_NONE:
2731 2720 default:
2732 2721 goto done;
2733 2722 }
2734 2723 length += ehdrlen;
2735 2724 whereptr += ehdrlen;
2736 2725 }
2737 2726 done:
2738 2727 if (nexthdrp != NULL)
2739 2728 *nexthdrp = nexthdr;
2740 2729 return (length);
2741 2730 }
2742 2731
2743 2732 /*
2744 2733 * Try to determine where and what are the IPv6 header length and
2745 2734 * pointer to nexthdr value for the upper layer protocol (or an
2746 2735 * unknown next hdr).
2747 2736 *
2748 2737 * Parameters returns a pointer to the nexthdr value;
2749 2738 * Must handle malformed packets of various sorts.
2750 2739 * Function returns failure for malformed cases.
2751 2740 */
2752 2741 boolean_t
2753 2742 ip_hdr_length_nexthdr_v6(mblk_t *mp, ip6_t *ip6h, uint16_t *hdr_length_ptr,
2754 2743 uint8_t **nexthdrpp)
2755 2744 {
2756 2745 uint16_t length;
2757 2746 uint_t ehdrlen;
2758 2747 uint8_t *nexthdrp;
2759 2748 uint8_t *whereptr;
2760 2749 uint8_t *endptr;
2761 2750 ip6_dest_t *desthdr;
2762 2751 ip6_rthdr_t *rthdr;
2763 2752 ip6_frag_t *fraghdr;
2764 2753
2765 2754 ASSERT(IPH_HDR_VERSION(ip6h) == IPV6_VERSION);
2766 2755 length = IPV6_HDR_LEN;
2767 2756 whereptr = ((uint8_t *)&ip6h[1]); /* point to next hdr */
2768 2757 endptr = mp->b_wptr;
2769 2758
2770 2759 nexthdrp = &ip6h->ip6_nxt;
2771 2760 while (whereptr < endptr) {
2772 2761 /* Is there enough left for len + nexthdr? */
2773 2762 if (whereptr + MIN_EHDR_LEN > endptr)
2774 2763 break;
2775 2764
2776 2765 switch (*nexthdrp) {
2777 2766 case IPPROTO_HOPOPTS:
2778 2767 case IPPROTO_DSTOPTS:
2779 2768 /* Assumes the headers are identical for hbh and dst */
2780 2769 desthdr = (ip6_dest_t *)whereptr;
2781 2770 ehdrlen = 8 * (desthdr->ip6d_len + 1);
2782 2771 if ((uchar_t *)desthdr + ehdrlen > endptr)
2783 2772 return (B_FALSE);
2784 2773 nexthdrp = &desthdr->ip6d_nxt;
2785 2774 break;
2786 2775 case IPPROTO_ROUTING:
2787 2776 rthdr = (ip6_rthdr_t *)whereptr;
2788 2777 ehdrlen = 8 * (rthdr->ip6r_len + 1);
2789 2778 if ((uchar_t *)rthdr + ehdrlen > endptr)
2790 2779 return (B_FALSE);
2791 2780 nexthdrp = &rthdr->ip6r_nxt;
2792 2781 break;
2793 2782 case IPPROTO_FRAGMENT:
2794 2783 fraghdr = (ip6_frag_t *)whereptr;
2795 2784 ehdrlen = sizeof (ip6_frag_t);
2796 2785 if ((uchar_t *)&fraghdr[1] > endptr)
2797 2786 return (B_FALSE);
2798 2787 nexthdrp = &fraghdr->ip6f_nxt;
2799 2788 break;
2800 2789 case IPPROTO_NONE:
2801 2790 /* No next header means we're finished */
2802 2791 default:
2803 2792 *hdr_length_ptr = length;
2804 2793 *nexthdrpp = nexthdrp;
2805 2794 return (B_TRUE);
2806 2795 }
2807 2796 length += ehdrlen;
2808 2797 whereptr += ehdrlen;
2809 2798 *hdr_length_ptr = length;
2810 2799 *nexthdrpp = nexthdrp;
2811 2800 }
2812 2801 switch (*nexthdrp) {
2813 2802 case IPPROTO_HOPOPTS:
2814 2803 case IPPROTO_DSTOPTS:
2815 2804 case IPPROTO_ROUTING:
2816 2805 case IPPROTO_FRAGMENT:
2817 2806 /*
2818 2807 * If any know extension headers are still to be processed,
2819 2808 * the packet's malformed (or at least all the IP header(s) are
2820 2809 * not in the same mblk - and that should never happen.
2821 2810 */
2822 2811 return (B_FALSE);
2823 2812
2824 2813 default:
2825 2814 /*
2826 2815 * If we get here, we know that all of the IP headers were in
2827 2816 * the same mblk, even if the ULP header is in the next mblk.
2828 2817 */
2829 2818 *hdr_length_ptr = length;
2830 2819 *nexthdrpp = nexthdrp;
2831 2820 return (B_TRUE);
2832 2821 }
2833 2822 }
2834 2823
2835 2824 /*
2836 2825 * Return the length of the IPv6 related headers (including extension headers)
2837 2826 * Returns a length even if the packet is malformed.
2838 2827 */
2839 2828 int
2840 2829 ip_hdr_length_v6(mblk_t *mp, ip6_t *ip6h)
2841 2830 {
2842 2831 uint16_t hdr_len;
2843 2832 uint8_t *nexthdrp;
2844 2833
2845 2834 (void) ip_hdr_length_nexthdr_v6(mp, ip6h, &hdr_len, &nexthdrp);
2846 2835 return (hdr_len);
2847 2836 }
2848 2837
2849 2838 /*
2850 2839 * Parse and process any hop-by-hop or destination options.
2851 2840 *
2852 2841 * Assumes that q is an ill read queue so that ICMP errors for link-local
2853 2842 * destinations are sent out the correct interface.
2854 2843 *
2855 2844 * Returns -1 if there was an error and mp has been consumed.
2856 2845 * Returns 0 if no special action is needed.
2857 2846 * Returns 1 if the packet contained a router alert option for this node
2858 2847 * which is verified to be "interesting/known" for our implementation.
2859 2848 *
2860 2849 * XXX Note: In future as more hbh or dest options are defined,
2861 2850 * it may be better to have different routines for hbh and dest
2862 2851 * options as opt_type fields other than IP6OPT_PAD1 and IP6OPT_PADN
2863 2852 * may have same value in different namespaces. Or is it same namespace ??
2864 2853 * Current code checks for each opt_type (other than pads) if it is in
2865 2854 * the expected nexthdr (hbh or dest)
2866 2855 */
2867 2856 int
2868 2857 ip_process_options_v6(mblk_t *mp, ip6_t *ip6h,
2869 2858 uint8_t *optptr, uint_t optlen, uint8_t hdr_type, ip_recv_attr_t *ira)
2870 2859 {
2871 2860 uint8_t opt_type;
2872 2861 uint_t optused;
2873 2862 int ret = 0;
2874 2863 const char *errtype;
2875 2864 ill_t *ill = ira->ira_ill;
2876 2865 ip_stack_t *ipst = ill->ill_ipst;
2877 2866
2878 2867 while (optlen != 0) {
2879 2868 opt_type = *optptr;
2880 2869 if (opt_type == IP6OPT_PAD1) {
2881 2870 optused = 1;
2882 2871 } else {
2883 2872 if (optlen < 2)
2884 2873 goto bad_opt;
2885 2874 errtype = "malformed";
2886 2875 if (opt_type == ip6opt_ls) {
2887 2876 optused = 2 + optptr[1];
2888 2877 if (optused > optlen)
2889 2878 goto bad_opt;
2890 2879 } else switch (opt_type) {
2891 2880 case IP6OPT_PADN:
2892 2881 /*
2893 2882 * Note:We don't verify that (N-2) pad octets
2894 2883 * are zero as required by spec. Adhere to
2895 2884 * "be liberal in what you accept..." part of
2896 2885 * implementation philosophy (RFC791,RFC1122)
2897 2886 */
2898 2887 optused = 2 + optptr[1];
2899 2888 if (optused > optlen)
2900 2889 goto bad_opt;
2901 2890 break;
2902 2891
2903 2892 case IP6OPT_JUMBO:
2904 2893 if (hdr_type != IPPROTO_HOPOPTS)
2905 2894 goto opt_error;
2906 2895 goto opt_error; /* XXX Not implemented! */
2907 2896
2908 2897 case IP6OPT_ROUTER_ALERT: {
2909 2898 struct ip6_opt_router *or;
2910 2899
2911 2900 if (hdr_type != IPPROTO_HOPOPTS)
2912 2901 goto opt_error;
2913 2902 optused = 2 + optptr[1];
2914 2903 if (optused > optlen)
2915 2904 goto bad_opt;
2916 2905 or = (struct ip6_opt_router *)optptr;
2917 2906 /* Check total length and alignment */
2918 2907 if (optused != sizeof (*or) ||
2919 2908 ((uintptr_t)or->ip6or_value & 0x1) != 0)
2920 2909 goto opt_error;
2921 2910 /* Check value */
2922 2911 switch (*((uint16_t *)or->ip6or_value)) {
2923 2912 case IP6_ALERT_MLD:
2924 2913 case IP6_ALERT_RSVP:
2925 2914 ret = 1;
2926 2915 }
2927 2916 break;
2928 2917 }
2929 2918 case IP6OPT_HOME_ADDRESS: {
2930 2919 /*
2931 2920 * Minimal support for the home address option
2932 2921 * (which is required by all IPv6 nodes).
2933 2922 * Implement by just swapping the home address
2934 2923 * and source address.
2935 2924 * XXX Note: this has IPsec implications since
2936 2925 * AH needs to take this into account.
2937 2926 * Also, when IPsec is used we need to ensure
2938 2927 * that this is only processed once
2939 2928 * in the received packet (to avoid swapping
2940 2929 * back and forth).
2941 2930 * NOTE:This option processing is considered
2942 2931 * to be unsafe and prone to a denial of
2943 2932 * service attack.
2944 2933 * The current processing is not safe even with
2945 2934 * IPsec secured IP packets. Since the home
2946 2935 * address option processing requirement still
2947 2936 * is in the IETF draft and in the process of
2948 2937 * being redefined for its usage, it has been
2949 2938 * decided to turn off the option by default.
2950 2939 * If this section of code needs to be executed,
2951 2940 * ndd variable ip6_ignore_home_address_opt
2952 2941 * should be set to 0 at the user's own risk.
2953 2942 */
2954 2943 struct ip6_opt_home_address *oh;
2955 2944 in6_addr_t tmp;
2956 2945
2957 2946 if (ipst->ips_ipv6_ignore_home_address_opt)
2958 2947 goto opt_error;
2959 2948
2960 2949 if (hdr_type != IPPROTO_DSTOPTS)
2961 2950 goto opt_error;
2962 2951 optused = 2 + optptr[1];
2963 2952 if (optused > optlen)
2964 2953 goto bad_opt;
2965 2954
2966 2955 /*
2967 2956 * We did this dest. opt the first time
2968 2957 * around (i.e. before AH processing).
2969 2958 * If we've done AH... stop now.
2970 2959 */
2971 2960 if ((ira->ira_flags & IRAF_IPSEC_SECURE) &&
2972 2961 ira->ira_ipsec_ah_sa != NULL)
2973 2962 break;
2974 2963
2975 2964 oh = (struct ip6_opt_home_address *)optptr;
2976 2965 /* Check total length and alignment */
2977 2966 if (optused < sizeof (*oh) ||
2978 2967 ((uintptr_t)oh->ip6oh_addr & 0x7) != 0)
2979 2968 goto opt_error;
2980 2969 /* Swap ip6_src and the home address */
2981 2970 tmp = ip6h->ip6_src;
2982 2971 /* XXX Note: only 8 byte alignment option */
2983 2972 ip6h->ip6_src = *(in6_addr_t *)oh->ip6oh_addr;
2984 2973 *(in6_addr_t *)oh->ip6oh_addr = tmp;
2985 2974 break;
2986 2975 }
2987 2976
2988 2977 case IP6OPT_TUNNEL_LIMIT:
2989 2978 if (hdr_type != IPPROTO_DSTOPTS) {
2990 2979 goto opt_error;
2991 2980 }
2992 2981 optused = 2 + optptr[1];
2993 2982 if (optused > optlen) {
2994 2983 goto bad_opt;
2995 2984 }
2996 2985 if (optused != 3) {
2997 2986 goto opt_error;
2998 2987 }
2999 2988 break;
3000 2989
3001 2990 default:
3002 2991 errtype = "unknown";
3003 2992 /* FALLTHROUGH */
3004 2993 opt_error:
3005 2994 /* Determine which zone should send error */
3006 2995 switch (IP6OPT_TYPE(opt_type)) {
3007 2996 case IP6OPT_TYPE_SKIP:
3008 2997 optused = 2 + optptr[1];
3009 2998 if (optused > optlen)
3010 2999 goto bad_opt;
3011 3000 ip1dbg(("ip_process_options_v6: %s "
3012 3001 "opt 0x%x skipped\n",
3013 3002 errtype, opt_type));
3014 3003 break;
3015 3004 case IP6OPT_TYPE_DISCARD:
3016 3005 ip1dbg(("ip_process_options_v6: %s "
3017 3006 "opt 0x%x; packet dropped\n",
3018 3007 errtype, opt_type));
3019 3008 BUMP_MIB(ill->ill_ip_mib,
3020 3009 ipIfStatsInHdrErrors);
3021 3010 ip_drop_input("ipIfStatsInHdrErrors",
3022 3011 mp, ill);
3023 3012 freemsg(mp);
3024 3013 return (-1);
3025 3014 case IP6OPT_TYPE_ICMP:
3026 3015 BUMP_MIB(ill->ill_ip_mib,
3027 3016 ipIfStatsInHdrErrors);
3028 3017 ip_drop_input("ipIfStatsInHdrErrors",
3029 3018 mp, ill);
3030 3019 icmp_param_problem_v6(mp,
3031 3020 ICMP6_PARAMPROB_OPTION,
3032 3021 (uint32_t)(optptr -
3033 3022 (uint8_t *)ip6h),
3034 3023 B_FALSE, ira);
3035 3024 return (-1);
3036 3025 case IP6OPT_TYPE_FORCEICMP:
3037 3026 BUMP_MIB(ill->ill_ip_mib,
3038 3027 ipIfStatsInHdrErrors);
3039 3028 ip_drop_input("ipIfStatsInHdrErrors",
3040 3029 mp, ill);
3041 3030 icmp_param_problem_v6(mp,
3042 3031 ICMP6_PARAMPROB_OPTION,
3043 3032 (uint32_t)(optptr -
3044 3033 (uint8_t *)ip6h),
3045 3034 B_TRUE, ira);
3046 3035 return (-1);
3047 3036 default:
3048 3037 ASSERT(0);
3049 3038 }
3050 3039 }
3051 3040 }
3052 3041 optlen -= optused;
3053 3042 optptr += optused;
3054 3043 }
3055 3044 return (ret);
3056 3045
3057 3046 bad_opt:
3058 3047 /* Determine which zone should send error */
3059 3048 ip_drop_input("ICMP_PARAM_PROBLEM", mp, ill);
3060 3049 icmp_param_problem_v6(mp, ICMP6_PARAMPROB_OPTION,
3061 3050 (uint32_t)(optptr - (uint8_t *)ip6h),
3062 3051 B_FALSE, ira);
3063 3052 return (-1);
3064 3053 }
3065 3054
3066 3055 /*
3067 3056 * Process a routing header that is not yet empty.
3068 3057 * Because of RFC 5095, we now reject all route headers.
3069 3058 */
3070 3059 void
3071 3060 ip_process_rthdr(mblk_t *mp, ip6_t *ip6h, ip6_rthdr_t *rth,
3072 3061 ip_recv_attr_t *ira)
3073 3062 {
3074 3063 ill_t *ill = ira->ira_ill;
3075 3064 ip_stack_t *ipst = ill->ill_ipst;
3076 3065
3077 3066 ASSERT(rth->ip6r_segleft != 0);
3078 3067
3079 3068 if (!ipst->ips_ipv6_forward_src_routed) {
3080 3069 /* XXX Check for source routed out same interface? */
3081 3070 BUMP_MIB(ill->ill_ip_mib, ipIfStatsForwProhibits);
3082 3071 BUMP_MIB(ill->ill_ip_mib, ipIfStatsInAddrErrors);
3083 3072 ip_drop_input("ipIfStatsInAddrErrors", mp, ill);
3084 3073 freemsg(mp);
3085 3074 return;
3086 3075 }
3087 3076
3088 3077 ip_drop_input("ICMP_PARAM_PROBLEM", mp, ill);
3089 3078 icmp_param_problem_v6(mp, ICMP6_PARAMPROB_HEADER,
3090 3079 (uint32_t)((uchar_t *)&rth->ip6r_type - (uchar_t *)ip6h),
3091 3080 B_FALSE, ira);
3092 3081 }
3093 3082
3094 3083 /*
3095 3084 * Read side put procedure for IPv6 module.
3096 3085 */
3097 3086 void
3098 3087 ip_rput_v6(queue_t *q, mblk_t *mp)
3099 3088 {
3100 3089 ill_t *ill;
3101 3090
3102 3091 ill = (ill_t *)q->q_ptr;
3103 3092 if (ill->ill_state_flags & (ILL_CONDEMNED | ILL_LL_SUBNET_PENDING)) {
3104 3093 union DL_primitives *dl;
3105 3094
3106 3095 dl = (union DL_primitives *)mp->b_rptr;
3107 3096 /*
3108 3097 * Things are opening or closing - only accept DLPI
3109 3098 * ack messages. If the stream is closing and ip_wsrv
3110 3099 * has completed, ip_close is out of the qwait, but has
3111 3100 * not yet completed qprocsoff. Don't proceed any further
3112 3101 * because the ill has been cleaned up and things hanging
3113 3102 * off the ill have been freed.
3114 3103 */
3115 3104 if ((mp->b_datap->db_type != M_PCPROTO) ||
3116 3105 (dl->dl_primitive == DL_UNITDATA_IND)) {
3117 3106 inet_freemsg(mp);
3118 3107 return;
3119 3108 }
3120 3109 }
3121 3110 if (DB_TYPE(mp) == M_DATA) {
3122 3111 struct mac_header_info_s mhi;
3123 3112
3124 3113 ip_mdata_to_mhi(ill, mp, &mhi);
3125 3114 ip_input_v6(ill, NULL, mp, &mhi);
3126 3115 } else {
3127 3116 ip_rput_notdata(ill, mp);
3128 3117 }
3129 3118 }
3130 3119
3131 3120 /*
3132 3121 * Walk through the IPv6 packet in mp and see if there's an AH header
3133 3122 * in it. See if the AH header needs to get done before other headers in
3134 3123 * the packet. (Worker function for ipsec_early_ah_v6().)
3135 3124 */
3136 3125 #define IPSEC_HDR_DONT_PROCESS 0
3137 3126 #define IPSEC_HDR_PROCESS 1
3138 3127 #define IPSEC_MEMORY_ERROR 2 /* or malformed packet */
3139 3128 static int
3140 3129 ipsec_needs_processing_v6(mblk_t *mp, uint8_t *nexthdr)
3141 3130 {
3142 3131 uint_t length;
3143 3132 uint_t ehdrlen;
3144 3133 uint8_t *whereptr;
3145 3134 uint8_t *endptr;
3146 3135 uint8_t *nexthdrp;
3147 3136 ip6_dest_t *desthdr;
3148 3137 ip6_rthdr_t *rthdr;
3149 3138 ip6_t *ip6h;
3150 3139
3151 3140 /*
3152 3141 * For now just pullup everything. In general, the less pullups,
3153 3142 * the better, but there's so much squirrelling through anyway,
3154 3143 * it's just easier this way.
3155 3144 */
3156 3145 if (!pullupmsg(mp, -1)) {
3157 3146 return (IPSEC_MEMORY_ERROR);
3158 3147 }
3159 3148
3160 3149 ip6h = (ip6_t *)mp->b_rptr;
3161 3150 length = IPV6_HDR_LEN;
3162 3151 whereptr = ((uint8_t *)&ip6h[1]); /* point to next hdr */
3163 3152 endptr = mp->b_wptr;
3164 3153
3165 3154 /*
3166 3155 * We can't just use the argument nexthdr in the place
3167 3156 * of nexthdrp becaue we don't dereference nexthdrp
3168 3157 * till we confirm whether it is a valid address.
3169 3158 */
3170 3159 nexthdrp = &ip6h->ip6_nxt;
3171 3160 while (whereptr < endptr) {
3172 3161 /* Is there enough left for len + nexthdr? */
3173 3162 if (whereptr + MIN_EHDR_LEN > endptr)
3174 3163 return (IPSEC_MEMORY_ERROR);
3175 3164
3176 3165 switch (*nexthdrp) {
3177 3166 case IPPROTO_HOPOPTS:
3178 3167 case IPPROTO_DSTOPTS:
3179 3168 /* Assumes the headers are identical for hbh and dst */
3180 3169 desthdr = (ip6_dest_t *)whereptr;
3181 3170 ehdrlen = 8 * (desthdr->ip6d_len + 1);
3182 3171 if ((uchar_t *)desthdr + ehdrlen > endptr)
3183 3172 return (IPSEC_MEMORY_ERROR);
3184 3173 /*
3185 3174 * Return DONT_PROCESS because the destination
3186 3175 * options header may be for each hop in a
3187 3176 * routing-header, and we only want AH if we're
3188 3177 * finished with routing headers.
3189 3178 */
3190 3179 if (*nexthdrp == IPPROTO_DSTOPTS)
3191 3180 return (IPSEC_HDR_DONT_PROCESS);
3192 3181 nexthdrp = &desthdr->ip6d_nxt;
3193 3182 break;
3194 3183 case IPPROTO_ROUTING:
3195 3184 rthdr = (ip6_rthdr_t *)whereptr;
3196 3185
3197 3186 /*
3198 3187 * If there's more hops left on the routing header,
3199 3188 * return now with DON'T PROCESS.
3200 3189 */
3201 3190 if (rthdr->ip6r_segleft > 0)
3202 3191 return (IPSEC_HDR_DONT_PROCESS);
3203 3192
3204 3193 ehdrlen = 8 * (rthdr->ip6r_len + 1);
3205 3194 if ((uchar_t *)rthdr + ehdrlen > endptr)
3206 3195 return (IPSEC_MEMORY_ERROR);
3207 3196 nexthdrp = &rthdr->ip6r_nxt;
3208 3197 break;
3209 3198 case IPPROTO_FRAGMENT:
3210 3199 /* Wait for reassembly */
3211 3200 return (IPSEC_HDR_DONT_PROCESS);
3212 3201 case IPPROTO_AH:
3213 3202 *nexthdr = IPPROTO_AH;
3214 3203 return (IPSEC_HDR_PROCESS);
3215 3204 case IPPROTO_NONE:
3216 3205 /* No next header means we're finished */
3217 3206 default:
3218 3207 return (IPSEC_HDR_DONT_PROCESS);
3219 3208 }
3220 3209 length += ehdrlen;
3221 3210 whereptr += ehdrlen;
3222 3211 }
3223 3212 /*
3224 3213 * Malformed/truncated packet.
3225 3214 */
3226 3215 return (IPSEC_MEMORY_ERROR);
3227 3216 }
3228 3217
3229 3218 /*
3230 3219 * Path for AH if options are present.
3231 3220 * Returns NULL if the mblk was consumed.
3232 3221 *
3233 3222 * Sometimes AH needs to be done before other IPv6 headers for security
3234 3223 * reasons. This function (and its ipsec_needs_processing_v6() above)
3235 3224 * indicates if that is so, and fans out to the appropriate IPsec protocol
3236 3225 * for the datagram passed in.
3237 3226 */
3238 3227 mblk_t *
3239 3228 ipsec_early_ah_v6(mblk_t *mp, ip_recv_attr_t *ira)
3240 3229 {
3241 3230 uint8_t nexthdr;
3242 3231 ah_t *ah;
3243 3232 ill_t *ill = ira->ira_ill;
3244 3233 ip_stack_t *ipst = ill->ill_ipst;
3245 3234 ipsec_stack_t *ipss = ipst->ips_netstack->netstack_ipsec;
3246 3235
3247 3236 switch (ipsec_needs_processing_v6(mp, &nexthdr)) {
3248 3237 case IPSEC_MEMORY_ERROR:
3249 3238 BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards);
3250 3239 ip_drop_input("ipIfStatsInDiscards", mp, ill);
3251 3240 freemsg(mp);
3252 3241 return (NULL);
3253 3242 case IPSEC_HDR_DONT_PROCESS:
3254 3243 return (mp);
3255 3244 }
3256 3245
3257 3246 /* Default means send it to AH! */
3258 3247 ASSERT(nexthdr == IPPROTO_AH);
3259 3248
3260 3249 if (!ipsec_loaded(ipss)) {
3261 3250 ip_proto_not_sup(mp, ira);
3262 3251 return (NULL);
3263 3252 }
3264 3253
3265 3254 mp = ipsec_inbound_ah_sa(mp, ira, &ah);
3266 3255 if (mp == NULL)
3267 3256 return (NULL);
3268 3257 ASSERT(ah != NULL);
3269 3258 ASSERT(ira->ira_flags & IRAF_IPSEC_SECURE);
3270 3259 ASSERT(ira->ira_ipsec_ah_sa != NULL);
3271 3260 ASSERT(ira->ira_ipsec_ah_sa->ipsa_input_func != NULL);
3272 3261 mp = ira->ira_ipsec_ah_sa->ipsa_input_func(mp, ah, ira);
3273 3262
3274 3263 if (mp == NULL) {
3275 3264 /*
3276 3265 * Either it failed or is pending. In the former case
3277 3266 * ipIfStatsInDiscards was increased.
3278 3267 */
3279 3268 return (NULL);
3280 3269 }
3281 3270
3282 3271 /* we're done with IPsec processing, send it up */
3283 3272 ip_input_post_ipsec(mp, ira);
3284 3273 return (NULL);
3285 3274 }
3286 3275
3287 3276 /*
3288 3277 * Reassemble fragment.
3289 3278 * When it returns a completed message the first mblk will only contain
3290 3279 * the headers prior to the fragment header, with the nexthdr value updated
3291 3280 * to be the header after the fragment header.
3292 3281 */
3293 3282 mblk_t *
3294 3283 ip_input_fragment_v6(mblk_t *mp, ip6_t *ip6h,
3295 3284 ip6_frag_t *fraghdr, uint_t remlen, ip_recv_attr_t *ira)
3296 3285 {
3297 3286 uint32_t ident = ntohl(fraghdr->ip6f_ident);
3298 3287 uint16_t offset;
3299 3288 boolean_t more_frags;
3300 3289 uint8_t nexthdr = fraghdr->ip6f_nxt;
3301 3290 in6_addr_t *v6dst_ptr;
3302 3291 in6_addr_t *v6src_ptr;
3303 3292 uint_t end;
3304 3293 uint_t hdr_length;
3305 3294 size_t count;
3306 3295 ipf_t *ipf;
3307 3296 ipf_t **ipfp;
3308 3297 ipfb_t *ipfb;
3309 3298 mblk_t *mp1;
3310 3299 uint8_t ecn_info = 0;
3311 3300 size_t msg_len;
3312 3301 mblk_t *tail_mp;
3313 3302 mblk_t *t_mp;
3314 3303 boolean_t pruned = B_FALSE;
3315 3304 uint32_t sum_val;
3316 3305 uint16_t sum_flags;
3317 3306 ill_t *ill = ira->ira_ill;
3318 3307 ip_stack_t *ipst = ill->ill_ipst;
3319 3308 uint_t prev_nexthdr_offset;
3320 3309 uint8_t prev_nexthdr;
3321 3310 uint8_t *ptr;
3322 3311 uint32_t packet_size;
3323 3312
3324 3313 /*
3325 3314 * We utilize hardware computed checksum info only for UDP since
3326 3315 * IP fragmentation is a normal occurence for the protocol. In
3327 3316 * addition, checksum offload support for IP fragments carrying
3328 3317 * UDP payload is commonly implemented across network adapters.
3329 3318 */
3330 3319 ASSERT(ira->ira_rill != NULL);
3331 3320 if (nexthdr == IPPROTO_UDP && dohwcksum &&
3332 3321 ILL_HCKSUM_CAPABLE(ira->ira_rill) &&
3333 3322 (DB_CKSUMFLAGS(mp) & (HCK_FULLCKSUM | HCK_PARTIALCKSUM))) {
3334 3323 mblk_t *mp1 = mp->b_cont;
3335 3324 int32_t len;
3336 3325
3337 3326 /* Record checksum information from the packet */
3338 3327 sum_val = (uint32_t)DB_CKSUM16(mp);
3339 3328 sum_flags = DB_CKSUMFLAGS(mp);
3340 3329
3341 3330 /* fragmented payload offset from beginning of mblk */
3342 3331 offset = (uint16_t)((uchar_t *)&fraghdr[1] - mp->b_rptr);
3343 3332
3344 3333 if ((sum_flags & HCK_PARTIALCKSUM) &&
3345 3334 (mp1 == NULL || mp1->b_cont == NULL) &&
3346 3335 offset >= DB_CKSUMSTART(mp) &&
3347 3336 ((len = offset - DB_CKSUMSTART(mp)) & 1) == 0) {
3348 3337 uint32_t adj;
3349 3338 /*
3350 3339 * Partial checksum has been calculated by hardware
3351 3340 * and attached to the packet; in addition, any
3352 3341 * prepended extraneous data is even byte aligned.
3353 3342 * If any such data exists, we adjust the checksum;
3354 3343 * this would also handle any postpended data.
3355 3344 */
3356 3345 IP_ADJCKSUM_PARTIAL(mp->b_rptr + DB_CKSUMSTART(mp),
3357 3346 mp, mp1, len, adj);
3358 3347
3359 3348 /* One's complement subtract extraneous checksum */
3360 3349 if (adj >= sum_val)
3361 3350 sum_val = ~(adj - sum_val) & 0xFFFF;
3362 3351 else
3363 3352 sum_val -= adj;
3364 3353 }
3365 3354 } else {
3366 3355 sum_val = 0;
3367 3356 sum_flags = 0;
3368 3357 }
3369 3358
3370 3359 /* Clear hardware checksumming flag */
3371 3360 DB_CKSUMFLAGS(mp) = 0;
3372 3361
3373 3362 /*
3374 3363 * Determine the offset (from the begining of the IP header)
3375 3364 * of the nexthdr value which has IPPROTO_FRAGMENT. We use
3376 3365 * this when removing the fragment header from the packet.
3377 3366 * This packet consists of the IPv6 header, a potential
3378 3367 * hop-by-hop options header, a potential pre-routing-header
3379 3368 * destination options header, and a potential routing header.
3380 3369 */
3381 3370 prev_nexthdr_offset = (uint8_t *)&ip6h->ip6_nxt - (uint8_t *)ip6h;
3382 3371 prev_nexthdr = ip6h->ip6_nxt;
3383 3372 ptr = (uint8_t *)&ip6h[1];
3384 3373
3385 3374 if (prev_nexthdr == IPPROTO_HOPOPTS) {
3386 3375 ip6_hbh_t *hbh_hdr;
3387 3376 uint_t hdr_len;
3388 3377
3389 3378 hbh_hdr = (ip6_hbh_t *)ptr;
3390 3379 hdr_len = 8 * (hbh_hdr->ip6h_len + 1);
3391 3380 prev_nexthdr = hbh_hdr->ip6h_nxt;
3392 3381 prev_nexthdr_offset = (uint8_t *)&hbh_hdr->ip6h_nxt
3393 3382 - (uint8_t *)ip6h;
3394 3383 ptr += hdr_len;
3395 3384 }
3396 3385 if (prev_nexthdr == IPPROTO_DSTOPTS) {
3397 3386 ip6_dest_t *dest_hdr;
3398 3387 uint_t hdr_len;
3399 3388
3400 3389 dest_hdr = (ip6_dest_t *)ptr;
3401 3390 hdr_len = 8 * (dest_hdr->ip6d_len + 1);
3402 3391 prev_nexthdr = dest_hdr->ip6d_nxt;
3403 3392 prev_nexthdr_offset = (uint8_t *)&dest_hdr->ip6d_nxt
3404 3393 - (uint8_t *)ip6h;
3405 3394 ptr += hdr_len;
3406 3395 }
3407 3396 if (prev_nexthdr == IPPROTO_ROUTING) {
3408 3397 ip6_rthdr_t *rthdr;
3409 3398 uint_t hdr_len;
3410 3399
3411 3400 rthdr = (ip6_rthdr_t *)ptr;
3412 3401 prev_nexthdr = rthdr->ip6r_nxt;
3413 3402 prev_nexthdr_offset = (uint8_t *)&rthdr->ip6r_nxt
3414 3403 - (uint8_t *)ip6h;
3415 3404 hdr_len = 8 * (rthdr->ip6r_len + 1);
3416 3405 ptr += hdr_len;
3417 3406 }
3418 3407 if (prev_nexthdr != IPPROTO_FRAGMENT) {
3419 3408 /* Can't handle other headers before the fragment header */
3420 3409 BUMP_MIB(ill->ill_ip_mib, ipIfStatsInHdrErrors);
3421 3410 ip_drop_input("ipIfStatsInHdrErrors", mp, ill);
3422 3411 freemsg(mp);
3423 3412 return (NULL);
3424 3413 }
3425 3414
3426 3415 /*
3427 3416 * Note: Fragment offset in header is in 8-octet units.
3428 3417 * Clearing least significant 3 bits not only extracts
3429 3418 * it but also gets it in units of octets.
3430 3419 */
3431 3420 offset = ntohs(fraghdr->ip6f_offlg) & ~7;
3432 3421 more_frags = (fraghdr->ip6f_offlg & IP6F_MORE_FRAG);
3433 3422
3434 3423 /*
3435 3424 * Is the more frags flag on and the payload length not a multiple
3436 3425 * of eight?
3437 3426 */
3438 3427 if (more_frags && (ntohs(ip6h->ip6_plen) & 7)) {
3439 3428 ip_drop_input("ICMP_PARAM_PROBLEM", mp, ill);
3440 3429 icmp_param_problem_v6(mp, ICMP6_PARAMPROB_HEADER,
3441 3430 (uint32_t)((char *)&ip6h->ip6_plen -
3442 3431 (char *)ip6h), B_FALSE, ira);
3443 3432 return (NULL);
3444 3433 }
3445 3434
3446 3435 v6src_ptr = &ip6h->ip6_src;
3447 3436 v6dst_ptr = &ip6h->ip6_dst;
3448 3437 end = remlen;
3449 3438
3450 3439 hdr_length = (uint_t)((char *)&fraghdr[1] - (char *)ip6h);
3451 3440 end += offset;
3452 3441
3453 3442 /*
3454 3443 * Would fragment cause reassembled packet to have a payload length
3455 3444 * greater than IP_MAXPACKET - the max payload size?
3456 3445 */
3457 3446 if (end > IP_MAXPACKET) {
3458 3447 BUMP_MIB(ill->ill_ip_mib, ipIfStatsInHdrErrors);
3459 3448 ip_drop_input("Reassembled packet too large", mp, ill);
3460 3449 icmp_param_problem_v6(mp, ICMP6_PARAMPROB_HEADER,
3461 3450 (uint32_t)((char *)&fraghdr->ip6f_offlg -
3462 3451 (char *)ip6h), B_FALSE, ira);
3463 3452 return (NULL);
3464 3453 }
3465 3454
3466 3455 /*
3467 3456 * This packet just has one fragment. Reassembly not
3468 3457 * needed.
3469 3458 */
3470 3459 if (!more_frags && offset == 0) {
3471 3460 goto reass_done;
3472 3461 }
3473 3462
3474 3463 /*
3475 3464 * Drop the fragmented as early as possible, if
3476 3465 * we don't have resource(s) to re-assemble.
3477 3466 */
3478 3467 if (ipst->ips_ip_reass_queue_bytes == 0) {
3479 3468 freemsg(mp);
3480 3469 return (NULL);
3481 3470 }
3482 3471
3483 3472 /* Record the ECN field info. */
3484 3473 ecn_info = (uint8_t)(ntohl(ip6h->ip6_vcf & htonl(~0xFFCFFFFF)) >> 20);
3485 3474 /*
3486 3475 * If this is not the first fragment, dump the unfragmentable
3487 3476 * portion of the packet.
3488 3477 */
3489 3478 if (offset)
3490 3479 mp->b_rptr = (uchar_t *)&fraghdr[1];
3491 3480
3492 3481 /*
3493 3482 * Fragmentation reassembly. Each ILL has a hash table for
3494 3483 * queueing packets undergoing reassembly for all IPIFs
3495 3484 * associated with the ILL. The hash is based on the packet
3496 3485 * IP ident field. The ILL frag hash table was allocated
3497 3486 * as a timer block at the time the ILL was created. Whenever
3498 3487 * there is anything on the reassembly queue, the timer will
3499 3488 * be running.
3500 3489 */
3501 3490 /* Handle vnic loopback of fragments */
3502 3491 if (mp->b_datap->db_ref > 2)
3503 3492 msg_len = 0;
3504 3493 else
3505 3494 msg_len = MBLKSIZE(mp);
3506 3495
3507 3496 tail_mp = mp;
3508 3497 while (tail_mp->b_cont != NULL) {
3509 3498 tail_mp = tail_mp->b_cont;
3510 3499 if (tail_mp->b_datap->db_ref <= 2)
3511 3500 msg_len += MBLKSIZE(tail_mp);
3512 3501 }
3513 3502 /*
3514 3503 * If the reassembly list for this ILL will get too big
3515 3504 * prune it.
3516 3505 */
3517 3506
3518 3507 if ((msg_len + sizeof (*ipf) + ill->ill_frag_count) >=
3519 3508 ipst->ips_ip_reass_queue_bytes) {
3520 3509 DTRACE_PROBE3(ip_reass_queue_bytes, uint_t, msg_len,
3521 3510 uint_t, ill->ill_frag_count,
3522 3511 uint_t, ipst->ips_ip_reass_queue_bytes);
3523 3512 ill_frag_prune(ill,
3524 3513 (ipst->ips_ip_reass_queue_bytes < msg_len) ? 0 :
3525 3514 (ipst->ips_ip_reass_queue_bytes - msg_len));
3526 3515 pruned = B_TRUE;
3527 3516 }
3528 3517
3529 3518 ipfb = &ill->ill_frag_hash_tbl[ILL_FRAG_HASH_V6(*v6src_ptr, ident)];
3530 3519 mutex_enter(&ipfb->ipfb_lock);
3531 3520
3532 3521 ipfp = &ipfb->ipfb_ipf;
3533 3522 /* Try to find an existing fragment queue for this packet. */
3534 3523 for (;;) {
3535 3524 ipf = ipfp[0];
3536 3525 if (ipf) {
3537 3526 /*
3538 3527 * It has to match on ident, source address, and
3539 3528 * dest address.
3540 3529 */
3541 3530 if (ipf->ipf_ident == ident &&
3542 3531 IN6_ARE_ADDR_EQUAL(&ipf->ipf_v6src, v6src_ptr) &&
3543 3532 IN6_ARE_ADDR_EQUAL(&ipf->ipf_v6dst, v6dst_ptr)) {
3544 3533
3545 3534 /*
3546 3535 * If we have received too many
3547 3536 * duplicate fragments for this packet
3548 3537 * free it.
3549 3538 */
3550 3539 if (ipf->ipf_num_dups > ip_max_frag_dups) {
3551 3540 ill_frag_free_pkts(ill, ipfb, ipf, 1);
3552 3541 freemsg(mp);
3553 3542 mutex_exit(&ipfb->ipfb_lock);
3554 3543 return (NULL);
3555 3544 }
3556 3545
3557 3546 break;
3558 3547 }
3559 3548 ipfp = &ipf->ipf_hash_next;
3560 3549 continue;
3561 3550 }
3562 3551
3563 3552
3564 3553 /*
3565 3554 * If we pruned the list, do we want to store this new
3566 3555 * fragment?. We apply an optimization here based on the
3567 3556 * fact that most fragments will be received in order.
3568 3557 * So if the offset of this incoming fragment is zero,
3569 3558 * it is the first fragment of a new packet. We will
3570 3559 * keep it. Otherwise drop the fragment, as we have
3571 3560 * probably pruned the packet already (since the
3572 3561 * packet cannot be found).
3573 3562 */
3574 3563
3575 3564 if (pruned && offset != 0) {
3576 3565 mutex_exit(&ipfb->ipfb_lock);
3577 3566 freemsg(mp);
3578 3567 return (NULL);
3579 3568 }
3580 3569
3581 3570 /* New guy. Allocate a frag message. */
3582 3571 mp1 = allocb(sizeof (*ipf), BPRI_MED);
3583 3572 if (!mp1) {
3584 3573 BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards);
3585 3574 ip_drop_input("ipIfStatsInDiscards", mp, ill);
3586 3575 freemsg(mp);
3587 3576 partial_reass_done:
3588 3577 mutex_exit(&ipfb->ipfb_lock);
3589 3578 return (NULL);
3590 3579 }
3591 3580
3592 3581 if (ipfb->ipfb_frag_pkts >= MAX_FRAG_PKTS(ipst)) {
3593 3582 /*
3594 3583 * Too many fragmented packets in this hash bucket.
3595 3584 * Free the oldest.
3596 3585 */
3597 3586 ill_frag_free_pkts(ill, ipfb, ipfb->ipfb_ipf, 1);
3598 3587 }
3599 3588
3600 3589 mp1->b_cont = mp;
3601 3590
3602 3591 /* Initialize the fragment header. */
3603 3592 ipf = (ipf_t *)mp1->b_rptr;
3604 3593 ipf->ipf_mp = mp1;
3605 3594 ipf->ipf_ptphn = ipfp;
3606 3595 ipfp[0] = ipf;
3607 3596 ipf->ipf_hash_next = NULL;
3608 3597 ipf->ipf_ident = ident;
3609 3598 ipf->ipf_v6src = *v6src_ptr;
3610 3599 ipf->ipf_v6dst = *v6dst_ptr;
3611 3600 /* Record reassembly start time. */
3612 3601 ipf->ipf_timestamp = gethrestime_sec();
3613 3602 /* Record ipf generation and account for frag header */
3614 3603 ipf->ipf_gen = ill->ill_ipf_gen++;
3615 3604 ipf->ipf_count = MBLKSIZE(mp1);
3616 3605 ipf->ipf_protocol = nexthdr;
3617 3606 ipf->ipf_nf_hdr_len = 0;
3618 3607 ipf->ipf_prev_nexthdr_offset = 0;
3619 3608 ipf->ipf_last_frag_seen = B_FALSE;
3620 3609 ipf->ipf_ecn = ecn_info;
3621 3610 ipf->ipf_num_dups = 0;
3622 3611 ipfb->ipfb_frag_pkts++;
3623 3612 ipf->ipf_checksum = 0;
3624 3613 ipf->ipf_checksum_flags = 0;
3625 3614
3626 3615 /* Store checksum value in fragment header */
3627 3616 if (sum_flags != 0) {
3628 3617 sum_val = (sum_val & 0xFFFF) + (sum_val >> 16);
3629 3618 sum_val = (sum_val & 0xFFFF) + (sum_val >> 16);
3630 3619 ipf->ipf_checksum = sum_val;
3631 3620 ipf->ipf_checksum_flags = sum_flags;
3632 3621 }
3633 3622
3634 3623 /*
3635 3624 * We handle reassembly two ways. In the easy case,
3636 3625 * where all the fragments show up in order, we do
3637 3626 * minimal bookkeeping, and just clip new pieces on
3638 3627 * the end. If we ever see a hole, then we go off
3639 3628 * to ip_reassemble which has to mark the pieces and
3640 3629 * keep track of the number of holes, etc. Obviously,
3641 3630 * the point of having both mechanisms is so we can
3642 3631 * handle the easy case as efficiently as possible.
3643 3632 */
3644 3633 if (offset == 0) {
3645 3634 /* Easy case, in-order reassembly so far. */
3646 3635 /* Update the byte count */
3647 3636 ipf->ipf_count += msg_len;
3648 3637 ipf->ipf_tail_mp = tail_mp;
3649 3638 /*
3650 3639 * Keep track of next expected offset in
3651 3640 * ipf_end.
3652 3641 */
3653 3642 ipf->ipf_end = end;
3654 3643 ipf->ipf_nf_hdr_len = hdr_length;
3655 3644 ipf->ipf_prev_nexthdr_offset = prev_nexthdr_offset;
3656 3645 } else {
3657 3646 /* Hard case, hole at the beginning. */
3658 3647 ipf->ipf_tail_mp = NULL;
3659 3648 /*
3660 3649 * ipf_end == 0 means that we have given up
3661 3650 * on easy reassembly.
3662 3651 */
3663 3652 ipf->ipf_end = 0;
3664 3653
3665 3654 /* Forget checksum offload from now on */
3666 3655 ipf->ipf_checksum_flags = 0;
3667 3656
3668 3657 /*
3669 3658 * ipf_hole_cnt is set by ip_reassemble.
3670 3659 * ipf_count is updated by ip_reassemble.
3671 3660 * No need to check for return value here
3672 3661 * as we don't expect reassembly to complete or
3673 3662 * fail for the first fragment itself.
3674 3663 */
3675 3664 (void) ip_reassemble(mp, ipf, offset, more_frags, ill,
3676 3665 msg_len);
3677 3666 }
3678 3667 /* Update per ipfb and ill byte counts */
3679 3668 ipfb->ipfb_count += ipf->ipf_count;
3680 3669 ASSERT(ipfb->ipfb_count > 0); /* Wraparound */
3681 3670 atomic_add_32(&ill->ill_frag_count, ipf->ipf_count);
3682 3671 /* If the frag timer wasn't already going, start it. */
3683 3672 mutex_enter(&ill->ill_lock);
3684 3673 ill_frag_timer_start(ill);
3685 3674 mutex_exit(&ill->ill_lock);
3686 3675 goto partial_reass_done;
3687 3676 }
3688 3677
3689 3678 /*
3690 3679 * If the packet's flag has changed (it could be coming up
3691 3680 * from an interface different than the previous, therefore
3692 3681 * possibly different checksum capability), then forget about
3693 3682 * any stored checksum states. Otherwise add the value to
3694 3683 * the existing one stored in the fragment header.
3695 3684 */
3696 3685 if (sum_flags != 0 && sum_flags == ipf->ipf_checksum_flags) {
3697 3686 sum_val += ipf->ipf_checksum;
3698 3687 sum_val = (sum_val & 0xFFFF) + (sum_val >> 16);
3699 3688 sum_val = (sum_val & 0xFFFF) + (sum_val >> 16);
3700 3689 ipf->ipf_checksum = sum_val;
3701 3690 } else if (ipf->ipf_checksum_flags != 0) {
3702 3691 /* Forget checksum offload from now on */
3703 3692 ipf->ipf_checksum_flags = 0;
3704 3693 }
3705 3694
3706 3695 /*
3707 3696 * We have a new piece of a datagram which is already being
3708 3697 * reassembled. Update the ECN info if all IP fragments
3709 3698 * are ECN capable. If there is one which is not, clear
3710 3699 * all the info. If there is at least one which has CE
3711 3700 * code point, IP needs to report that up to transport.
3712 3701 */
3713 3702 if (ecn_info != IPH_ECN_NECT && ipf->ipf_ecn != IPH_ECN_NECT) {
3714 3703 if (ecn_info == IPH_ECN_CE)
3715 3704 ipf->ipf_ecn = IPH_ECN_CE;
3716 3705 } else {
3717 3706 ipf->ipf_ecn = IPH_ECN_NECT;
3718 3707 }
3719 3708
3720 3709 if (offset && ipf->ipf_end == offset) {
3721 3710 /* The new fragment fits at the end */
3722 3711 ipf->ipf_tail_mp->b_cont = mp;
3723 3712 /* Update the byte count */
3724 3713 ipf->ipf_count += msg_len;
3725 3714 /* Update per ipfb and ill byte counts */
3726 3715 ipfb->ipfb_count += msg_len;
3727 3716 ASSERT(ipfb->ipfb_count > 0); /* Wraparound */
3728 3717 atomic_add_32(&ill->ill_frag_count, msg_len);
3729 3718 if (more_frags) {
3730 3719 /* More to come. */
3731 3720 ipf->ipf_end = end;
3732 3721 ipf->ipf_tail_mp = tail_mp;
3733 3722 goto partial_reass_done;
3734 3723 }
3735 3724 } else {
3736 3725 /*
3737 3726 * Go do the hard cases.
3738 3727 * Call ip_reassemble().
3739 3728 */
3740 3729 int ret;
3741 3730
3742 3731 if (offset == 0) {
3743 3732 if (ipf->ipf_prev_nexthdr_offset == 0) {
3744 3733 ipf->ipf_nf_hdr_len = hdr_length;
3745 3734 ipf->ipf_prev_nexthdr_offset =
3746 3735 prev_nexthdr_offset;
3747 3736 }
3748 3737 }
3749 3738 /* Save current byte count */
3750 3739 count = ipf->ipf_count;
3751 3740 ret = ip_reassemble(mp, ipf, offset, more_frags, ill, msg_len);
3752 3741
3753 3742 /* Count of bytes added and subtracted (freeb()ed) */
3754 3743 count = ipf->ipf_count - count;
3755 3744 if (count) {
3756 3745 /* Update per ipfb and ill byte counts */
3757 3746 ipfb->ipfb_count += count;
3758 3747 ASSERT(ipfb->ipfb_count > 0); /* Wraparound */
3759 3748 atomic_add_32(&ill->ill_frag_count, count);
3760 3749 }
3761 3750 if (ret == IP_REASS_PARTIAL) {
3762 3751 goto partial_reass_done;
3763 3752 } else if (ret == IP_REASS_FAILED) {
3764 3753 /* Reassembly failed. Free up all resources */
3765 3754 ill_frag_free_pkts(ill, ipfb, ipf, 1);
3766 3755 for (t_mp = mp; t_mp != NULL; t_mp = t_mp->b_cont) {
3767 3756 IP_REASS_SET_START(t_mp, 0);
3768 3757 IP_REASS_SET_END(t_mp, 0);
3769 3758 }
3770 3759 freemsg(mp);
3771 3760 goto partial_reass_done;
3772 3761 }
3773 3762
3774 3763 /* We will reach here iff 'ret' is IP_REASS_COMPLETE */
3775 3764 }
3776 3765 /*
3777 3766 * We have completed reassembly. Unhook the frag header from
3778 3767 * the reassembly list.
3779 3768 *
3780 3769 * Grab the unfragmentable header length next header value out
3781 3770 * of the first fragment
3782 3771 */
3783 3772 ASSERT(ipf->ipf_nf_hdr_len != 0);
3784 3773 hdr_length = ipf->ipf_nf_hdr_len;
3785 3774
3786 3775 /*
3787 3776 * Before we free the frag header, record the ECN info
3788 3777 * to report back to the transport.
3789 3778 */
3790 3779 ecn_info = ipf->ipf_ecn;
3791 3780
3792 3781 /*
3793 3782 * Store the nextheader field in the header preceding the fragment
3794 3783 * header
3795 3784 */
3796 3785 nexthdr = ipf->ipf_protocol;
3797 3786 prev_nexthdr_offset = ipf->ipf_prev_nexthdr_offset;
3798 3787 ipfp = ipf->ipf_ptphn;
3799 3788
3800 3789 /* We need to supply these to caller */
3801 3790 if ((sum_flags = ipf->ipf_checksum_flags) != 0)
3802 3791 sum_val = ipf->ipf_checksum;
3803 3792 else
3804 3793 sum_val = 0;
3805 3794
3806 3795 mp1 = ipf->ipf_mp;
3807 3796 count = ipf->ipf_count;
3808 3797 ipf = ipf->ipf_hash_next;
3809 3798 if (ipf)
3810 3799 ipf->ipf_ptphn = ipfp;
3811 3800 ipfp[0] = ipf;
3812 3801 atomic_add_32(&ill->ill_frag_count, -count);
3813 3802 ASSERT(ipfb->ipfb_count >= count);
3814 3803 ipfb->ipfb_count -= count;
3815 3804 ipfb->ipfb_frag_pkts--;
3816 3805 mutex_exit(&ipfb->ipfb_lock);
3817 3806 /* Ditch the frag header. */
3818 3807 mp = mp1->b_cont;
3819 3808 freeb(mp1);
3820 3809
3821 3810 /*
3822 3811 * Make sure the packet is good by doing some sanity
3823 3812 * check. If bad we can silentely drop the packet.
3824 3813 */
3825 3814 reass_done:
3826 3815 if (hdr_length < sizeof (ip6_frag_t)) {
3827 3816 BUMP_MIB(ill->ill_ip_mib, ipIfStatsInHdrErrors);
3828 3817 ip_drop_input("ipIfStatsInHdrErrors", mp, ill);
3829 3818 ip1dbg(("ip_input_fragment_v6: bad packet\n"));
3830 3819 freemsg(mp);
3831 3820 return (NULL);
3832 3821 }
3833 3822
3834 3823 /*
3835 3824 * Remove the fragment header from the initial header by
3836 3825 * splitting the mblk into the non-fragmentable header and
3837 3826 * everthing after the fragment extension header. This has the
3838 3827 * side effect of putting all the headers that need destination
3839 3828 * processing into the b_cont block-- on return this fact is
3840 3829 * used in order to avoid having to look at the extensions
3841 3830 * already processed.
3842 3831 *
3843 3832 * Note that this code assumes that the unfragmentable portion
3844 3833 * of the header is in the first mblk and increments
3845 3834 * the read pointer past it. If this assumption is broken
3846 3835 * this code fails badly.
3847 3836 */
3848 3837 if (mp->b_rptr + hdr_length != mp->b_wptr) {
3849 3838 mblk_t *nmp;
3850 3839
3851 3840 if (!(nmp = dupb(mp))) {
3852 3841 ip1dbg(("ip_input_fragment_v6: dupb failed\n"));
3853 3842 BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards);
3854 3843 ip_drop_input("ipIfStatsInDiscards", mp, ill);
3855 3844 freemsg(mp);
3856 3845 return (NULL);
3857 3846 }
3858 3847 nmp->b_cont = mp->b_cont;
3859 3848 mp->b_cont = nmp;
3860 3849 nmp->b_rptr += hdr_length;
3861 3850 }
3862 3851 mp->b_wptr = mp->b_rptr + hdr_length - sizeof (ip6_frag_t);
3863 3852
3864 3853 ip6h = (ip6_t *)mp->b_rptr;
3865 3854 ((char *)ip6h)[prev_nexthdr_offset] = nexthdr;
3866 3855
3867 3856 /* Restore original IP length in header. */
3868 3857 packet_size = msgdsize(mp);
3869 3858 ip6h->ip6_plen = htons((uint16_t)(packet_size - IPV6_HDR_LEN));
3870 3859 /* Record the ECN info. */
3871 3860 ip6h->ip6_vcf &= htonl(0xFFCFFFFF);
3872 3861 ip6h->ip6_vcf |= htonl(ecn_info << 20);
3873 3862
3874 3863 /* Update the receive attributes */
3875 3864 ira->ira_pktlen = packet_size;
3876 3865 ira->ira_ip_hdr_length = hdr_length - sizeof (ip6_frag_t);
3877 3866 ira->ira_protocol = nexthdr;
3878 3867
3879 3868 /* Reassembly is successful; set checksum information in packet */
3880 3869 DB_CKSUM16(mp) = (uint16_t)sum_val;
3881 3870 DB_CKSUMFLAGS(mp) = sum_flags;
3882 3871 DB_CKSUMSTART(mp) = ira->ira_ip_hdr_length;
3883 3872
3884 3873 return (mp);
3885 3874 }
3886 3875
3887 3876 /*
3888 3877 * Given an mblk and a ptr, find the destination address in an IPv6 routing
3889 3878 * header.
3890 3879 */
3891 3880 static in6_addr_t
3892 3881 pluck_out_dst(const mblk_t *mp, uint8_t *whereptr, in6_addr_t oldrv)
3893 3882 {
3894 3883 ip6_rthdr0_t *rt0;
3895 3884 int segleft, numaddr;
3896 3885 in6_addr_t *ap, rv = oldrv;
3897 3886
3898 3887 rt0 = (ip6_rthdr0_t *)whereptr;
3899 3888 if (rt0->ip6r0_type != 0 && rt0->ip6r0_type != 2) {
3900 3889 DTRACE_PROBE2(pluck_out_dst_unknown_type, mblk_t *, mp,
3901 3890 uint8_t *, whereptr);
3902 3891 return (rv);
3903 3892 }
3904 3893 segleft = rt0->ip6r0_segleft;
3905 3894 numaddr = rt0->ip6r0_len / 2;
3906 3895
3907 3896 if ((rt0->ip6r0_len & 0x1) ||
3908 3897 (mp != NULL && whereptr + (rt0->ip6r0_len + 1) * 8 > mp->b_wptr) ||
3909 3898 (segleft > rt0->ip6r0_len / 2)) {
3910 3899 /*
3911 3900 * Corrupt packet. Either the routing header length is odd
3912 3901 * (can't happen) or mismatched compared to the packet, or the
3913 3902 * number of addresses is. Return what we can. This will
3914 3903 * only be a problem on forwarded packets that get squeezed
3915 3904 * through an outbound tunnel enforcing IPsec Tunnel Mode.
3916 3905 */
3917 3906 DTRACE_PROBE2(pluck_out_dst_badpkt, mblk_t *, mp, uint8_t *,
3918 3907 whereptr);
3919 3908 return (rv);
3920 3909 }
3921 3910
3922 3911 if (segleft != 0) {
3923 3912 ap = (in6_addr_t *)((char *)rt0 + sizeof (*rt0));
3924 3913 rv = ap[numaddr - 1];
3925 3914 }
3926 3915
3927 3916 return (rv);
3928 3917 }
3929 3918
3930 3919 /*
3931 3920 * Walk through the options to see if there is a routing header.
3932 3921 * If present get the destination which is the last address of
3933 3922 * the option.
3934 3923 * mp needs to be provided in cases when the extension headers might span
3935 3924 * b_cont; mp is never modified by this function.
3936 3925 */
3937 3926 in6_addr_t
3938 3927 ip_get_dst_v6(ip6_t *ip6h, const mblk_t *mp, boolean_t *is_fragment)
3939 3928 {
3940 3929 const mblk_t *current_mp = mp;
3941 3930 uint8_t nexthdr;
3942 3931 uint8_t *whereptr;
3943 3932 int ehdrlen;
3944 3933 in6_addr_t rv;
3945 3934
3946 3935 whereptr = (uint8_t *)ip6h;
3947 3936 ehdrlen = sizeof (ip6_t);
3948 3937
3949 3938 /* We assume at least the IPv6 base header is within one mblk. */
3950 3939 ASSERT(mp == NULL ||
3951 3940 (mp->b_rptr <= whereptr && mp->b_wptr >= whereptr + ehdrlen));
3952 3941
3953 3942 rv = ip6h->ip6_dst;
3954 3943 nexthdr = ip6h->ip6_nxt;
3955 3944 if (is_fragment != NULL)
3956 3945 *is_fragment = B_FALSE;
3957 3946
3958 3947 /*
3959 3948 * We also assume (thanks to ipsec_tun_outbound()'s pullup) that
3960 3949 * no extension headers will be split across mblks.
3961 3950 */
3962 3951
3963 3952 while (nexthdr == IPPROTO_HOPOPTS || nexthdr == IPPROTO_DSTOPTS ||
3964 3953 nexthdr == IPPROTO_ROUTING) {
3965 3954 if (nexthdr == IPPROTO_ROUTING)
3966 3955 rv = pluck_out_dst(current_mp, whereptr, rv);
3967 3956
3968 3957 /*
3969 3958 * All IPv6 extension headers have the next-header in byte
3970 3959 * 0, and the (length - 8) in 8-byte-words.
3971 3960 */
3972 3961 while (current_mp != NULL &&
3973 3962 whereptr + ehdrlen >= current_mp->b_wptr) {
3974 3963 ehdrlen -= (current_mp->b_wptr - whereptr);
3975 3964 current_mp = current_mp->b_cont;
3976 3965 if (current_mp == NULL) {
3977 3966 /* Bad packet. Return what we can. */
3978 3967 DTRACE_PROBE3(ip_get_dst_v6_badpkt, mblk_t *,
3979 3968 mp, mblk_t *, current_mp, ip6_t *, ip6h);
3980 3969 goto done;
3981 3970 }
3982 3971 whereptr = current_mp->b_rptr;
3983 3972 }
3984 3973 whereptr += ehdrlen;
3985 3974
3986 3975 nexthdr = *whereptr;
3987 3976 ASSERT(current_mp == NULL || whereptr + 1 < current_mp->b_wptr);
3988 3977 ehdrlen = (*(whereptr + 1) + 1) * 8;
3989 3978 }
3990 3979
3991 3980 done:
3992 3981 if (nexthdr == IPPROTO_FRAGMENT && is_fragment != NULL)
3993 3982 *is_fragment = B_TRUE;
3994 3983 return (rv);
3995 3984 }
3996 3985
3997 3986 /*
3998 3987 * ip_source_routed_v6:
3999 3988 * This function is called by redirect code (called from ip_input_v6) to
4000 3989 * know whether this packet is source routed through this node i.e
4001 3990 * whether this node (router) is part of the journey. This
4002 3991 * function is called under two cases :
4003 3992 *
4004 3993 * case 1 : Routing header was processed by this node and
4005 3994 * ip_process_rthdr replaced ip6_dst with the next hop
4006 3995 * and we are forwarding the packet to the next hop.
4007 3996 *
4008 3997 * case 2 : Routing header was not processed by this node and we
4009 3998 * are just forwarding the packet.
4010 3999 *
4011 4000 * For case (1) we don't want to send redirects. For case(2) we
4012 4001 * want to send redirects.
4013 4002 */
4014 4003 static boolean_t
4015 4004 ip_source_routed_v6(ip6_t *ip6h, mblk_t *mp, ip_stack_t *ipst)
4016 4005 {
4017 4006 uint8_t nexthdr;
4018 4007 in6_addr_t *addrptr;
4019 4008 ip6_rthdr0_t *rthdr;
4020 4009 uint8_t numaddr;
4021 4010 ip6_hbh_t *hbhhdr;
4022 4011 uint_t ehdrlen;
4023 4012 uint8_t *byteptr;
4024 4013
4025 4014 ip2dbg(("ip_source_routed_v6\n"));
4026 4015 nexthdr = ip6h->ip6_nxt;
4027 4016 ehdrlen = IPV6_HDR_LEN;
4028 4017
4029 4018 /* if a routing hdr is preceeded by HOPOPT or DSTOPT */
4030 4019 while (nexthdr == IPPROTO_HOPOPTS ||
4031 4020 nexthdr == IPPROTO_DSTOPTS) {
4032 4021 byteptr = (uint8_t *)ip6h + ehdrlen;
4033 4022 /*
4034 4023 * Check if we have already processed
4035 4024 * packets or we are just a forwarding
4036 4025 * router which only pulled up msgs up
4037 4026 * to IPV6HDR and one HBH ext header
4038 4027 */
4039 4028 if (byteptr + MIN_EHDR_LEN > mp->b_wptr) {
4040 4029 ip2dbg(("ip_source_routed_v6: Extension"
4041 4030 " headers not processed\n"));
4042 4031 return (B_FALSE);
4043 4032 }
4044 4033 hbhhdr = (ip6_hbh_t *)byteptr;
4045 4034 nexthdr = hbhhdr->ip6h_nxt;
4046 4035 ehdrlen = ehdrlen + 8 * (hbhhdr->ip6h_len + 1);
4047 4036 }
4048 4037 switch (nexthdr) {
4049 4038 case IPPROTO_ROUTING:
4050 4039 byteptr = (uint8_t *)ip6h + ehdrlen;
4051 4040 /*
4052 4041 * If for some reason, we haven't pulled up
4053 4042 * the routing hdr data mblk, then we must
4054 4043 * not have processed it at all. So for sure
4055 4044 * we are not part of the source routed journey.
4056 4045 */
4057 4046 if (byteptr + MIN_EHDR_LEN > mp->b_wptr) {
4058 4047 ip2dbg(("ip_source_routed_v6: Routing"
4059 4048 " header not processed\n"));
4060 4049 return (B_FALSE);
4061 4050 }
4062 4051 rthdr = (ip6_rthdr0_t *)byteptr;
4063 4052 /*
4064 4053 * Either we are an intermediate router or the
4065 4054 * last hop before destination and we have
4066 4055 * already processed the routing header.
4067 4056 * If segment_left is greater than or equal to zero,
4068 4057 * then we must be the (numaddr - segleft) entry
4069 4058 * of the routing header. Although ip6r0_segleft
4070 4059 * is a unit8_t variable, we still check for zero
4071 4060 * or greater value, if in case the data type
4072 4061 * is changed someday in future.
4073 4062 */
4074 4063 if (rthdr->ip6r0_segleft > 0 ||
4075 4064 rthdr->ip6r0_segleft == 0) {
4076 4065 numaddr = rthdr->ip6r0_len / 2;
4077 4066 addrptr = (in6_addr_t *)((char *)rthdr +
4078 4067 sizeof (*rthdr));
4079 4068 addrptr += (numaddr - (rthdr->ip6r0_segleft + 1));
4080 4069 if (addrptr != NULL) {
4081 4070 if (ip_type_v6(addrptr, ipst) == IRE_LOCAL)
4082 4071 return (B_TRUE);
4083 4072 ip1dbg(("ip_source_routed_v6: Not local\n"));
4084 4073 }
4085 4074 }
4086 4075 /* FALLTHRU */
4087 4076 default:
4088 4077 ip2dbg(("ip_source_routed_v6: Not source routed here\n"));
4089 4078 return (B_FALSE);
4090 4079 }
4091 4080 }
4092 4081
4093 4082 /*
4094 4083 * IPv6 fragmentation. Essentially the same as IPv4 fragmentation.
4095 4084 * We have not optimized this in terms of number of mblks
4096 4085 * allocated. For instance, for each fragment sent we always allocate a
4097 4086 * mblk to hold the IPv6 header and fragment header.
4098 4087 *
4099 4088 * Assumes that all the extension headers are contained in the first mblk
4100 4089 * and that the fragment header has has already been added by calling
4101 4090 * ip_fraghdr_add_v6.
4102 4091 */
4103 4092 int
4104 4093 ip_fragment_v6(mblk_t *mp, nce_t *nce, iaflags_t ixaflags, uint_t pkt_len,
4105 4094 uint32_t max_frag, uint32_t xmit_hint, zoneid_t szone, zoneid_t nolzid,
4106 4095 pfirepostfrag_t postfragfn, uintptr_t *ixa_cookie)
4107 4096 {
4108 4097 ip6_t *ip6h = (ip6_t *)mp->b_rptr;
4109 4098 ip6_t *fip6h;
4110 4099 mblk_t *hmp;
4111 4100 mblk_t *hmp0;
4112 4101 mblk_t *dmp;
4113 4102 ip6_frag_t *fraghdr;
4114 4103 size_t unfragmentable_len;
4115 4104 size_t mlen;
4116 4105 size_t max_chunk;
4117 4106 uint16_t off_flags;
4118 4107 uint16_t offset = 0;
4119 4108 ill_t *ill = nce->nce_ill;
4120 4109 uint8_t nexthdr;
4121 4110 uint8_t *ptr;
4122 4111 ip_stack_t *ipst = ill->ill_ipst;
4123 4112 uint_t priority = mp->b_band;
4124 4113 int error = 0;
4125 4114
4126 4115 BUMP_MIB(ill->ill_ip_mib, ipIfStatsOutFragReqds);
4127 4116 if (max_frag == 0) {
4128 4117 BUMP_MIB(ill->ill_ip_mib, ipIfStatsOutFragFails);
4129 4118 ip_drop_output("FragFails: zero max_frag", mp, ill);
4130 4119 freemsg(mp);
4131 4120 return (EINVAL);
4132 4121 }
4133 4122
4134 4123 /*
4135 4124 * Caller should have added fraghdr_t to pkt_len, and also
4136 4125 * updated ip6_plen.
4137 4126 */
4138 4127 ASSERT(ntohs(ip6h->ip6_plen) + IPV6_HDR_LEN == pkt_len);
4139 4128 ASSERT(msgdsize(mp) == pkt_len);
4140 4129
4141 4130 /*
4142 4131 * Determine the length of the unfragmentable portion of this
4143 4132 * datagram. This consists of the IPv6 header, a potential
4144 4133 * hop-by-hop options header, a potential pre-routing-header
4145 4134 * destination options header, and a potential routing header.
4146 4135 */
4147 4136 nexthdr = ip6h->ip6_nxt;
4148 4137 ptr = (uint8_t *)&ip6h[1];
4149 4138
4150 4139 if (nexthdr == IPPROTO_HOPOPTS) {
4151 4140 ip6_hbh_t *hbh_hdr;
4152 4141 uint_t hdr_len;
4153 4142
4154 4143 hbh_hdr = (ip6_hbh_t *)ptr;
4155 4144 hdr_len = 8 * (hbh_hdr->ip6h_len + 1);
4156 4145 nexthdr = hbh_hdr->ip6h_nxt;
4157 4146 ptr += hdr_len;
4158 4147 }
4159 4148 if (nexthdr == IPPROTO_DSTOPTS) {
4160 4149 ip6_dest_t *dest_hdr;
4161 4150 uint_t hdr_len;
4162 4151
4163 4152 dest_hdr = (ip6_dest_t *)ptr;
4164 4153 if (dest_hdr->ip6d_nxt == IPPROTO_ROUTING) {
4165 4154 hdr_len = 8 * (dest_hdr->ip6d_len + 1);
4166 4155 nexthdr = dest_hdr->ip6d_nxt;
4167 4156 ptr += hdr_len;
4168 4157 }
4169 4158 }
4170 4159 if (nexthdr == IPPROTO_ROUTING) {
4171 4160 ip6_rthdr_t *rthdr;
4172 4161 uint_t hdr_len;
4173 4162
4174 4163 rthdr = (ip6_rthdr_t *)ptr;
4175 4164 nexthdr = rthdr->ip6r_nxt;
4176 4165 hdr_len = 8 * (rthdr->ip6r_len + 1);
4177 4166 ptr += hdr_len;
4178 4167 }
4179 4168 if (nexthdr != IPPROTO_FRAGMENT) {
4180 4169 BUMP_MIB(ill->ill_ip_mib, ipIfStatsOutFragFails);
4181 4170 ip_drop_output("FragFails: bad nexthdr", mp, ill);
4182 4171 freemsg(mp);
4183 4172 return (EINVAL);
4184 4173 }
4185 4174 unfragmentable_len = (uint_t)(ptr - (uint8_t *)ip6h);
4186 4175 unfragmentable_len += sizeof (ip6_frag_t);
4187 4176
4188 4177 max_chunk = (max_frag - unfragmentable_len) & ~7;
4189 4178
4190 4179 /*
4191 4180 * Allocate an mblk with enough room for the link-layer
4192 4181 * header and the unfragmentable part of the datagram, which includes
4193 4182 * the fragment header. This (or a copy) will be used as the
4194 4183 * first mblk for each fragment we send.
4195 4184 */
4196 4185 hmp = allocb_tmpl(unfragmentable_len + ipst->ips_ip_wroff_extra, mp);
4197 4186 if (hmp == NULL) {
4198 4187 BUMP_MIB(ill->ill_ip_mib, ipIfStatsOutFragFails);
4199 4188 ip_drop_output("FragFails: no hmp", mp, ill);
4200 4189 freemsg(mp);
4201 4190 return (ENOBUFS);
4202 4191 }
4203 4192 hmp->b_rptr += ipst->ips_ip_wroff_extra;
4204 4193 hmp->b_wptr = hmp->b_rptr + unfragmentable_len;
4205 4194
4206 4195 fip6h = (ip6_t *)hmp->b_rptr;
4207 4196 bcopy(ip6h, fip6h, unfragmentable_len);
4208 4197
4209 4198 /*
4210 4199 * pkt_len is set to the total length of the fragmentable data in this
4211 4200 * datagram. For each fragment sent, we will decrement pkt_len
4212 4201 * by the amount of fragmentable data sent in that fragment
4213 4202 * until len reaches zero.
4214 4203 */
4215 4204 pkt_len -= unfragmentable_len;
4216 4205
4217 4206 /*
4218 4207 * Move read ptr past unfragmentable portion, we don't want this part
4219 4208 * of the data in our fragments.
4220 4209 */
4221 4210 mp->b_rptr += unfragmentable_len;
4222 4211 if (mp->b_rptr == mp->b_wptr) {
4223 4212 mblk_t *mp1 = mp->b_cont;
4224 4213 freeb(mp);
4225 4214 mp = mp1;
4226 4215 }
4227 4216
4228 4217 while (pkt_len != 0) {
4229 4218 mlen = MIN(pkt_len, max_chunk);
4230 4219 pkt_len -= mlen;
4231 4220 if (pkt_len != 0) {
4232 4221 /* Not last */
4233 4222 hmp0 = copyb(hmp);
4234 4223 if (hmp0 == NULL) {
4235 4224 BUMP_MIB(ill->ill_ip_mib,
4236 4225 ipIfStatsOutFragFails);
4237 4226 ip_drop_output("FragFails: copyb failed",
4238 4227 mp, ill);
4239 4228 freeb(hmp);
4240 4229 freemsg(mp);
4241 4230 ip1dbg(("ip_fragment_v6: copyb failed\n"));
4242 4231 return (ENOBUFS);
4243 4232 }
4244 4233 off_flags = IP6F_MORE_FRAG;
4245 4234 } else {
4246 4235 /* Last fragment */
4247 4236 hmp0 = hmp;
4248 4237 hmp = NULL;
4249 4238 off_flags = 0;
4250 4239 }
4251 4240 fip6h = (ip6_t *)(hmp0->b_rptr);
4252 4241 fraghdr = (ip6_frag_t *)(hmp0->b_rptr + unfragmentable_len -
4253 4242 sizeof (ip6_frag_t));
4254 4243
4255 4244 fip6h->ip6_plen = htons((uint16_t)(mlen +
4256 4245 unfragmentable_len - IPV6_HDR_LEN));
4257 4246 /*
4258 4247 * Note: Optimization alert.
4259 4248 * In IPv6 (and IPv4) protocol header, Fragment Offset
4260 4249 * ("offset") is 13 bits wide and in 8-octet units.
4261 4250 * In IPv6 protocol header (unlike IPv4) in a 16 bit field,
4262 4251 * it occupies the most significant 13 bits.
4263 4252 * (least significant 13 bits in IPv4).
4264 4253 * We do not do any shifts here. Not shifting is same effect
4265 4254 * as taking offset value in octet units, dividing by 8 and
4266 4255 * then shifting 3 bits left to line it up in place in proper
4267 4256 * place protocol header.
4268 4257 */
4269 4258 fraghdr->ip6f_offlg = htons(offset) | off_flags;
4270 4259
4271 4260 if (!(dmp = ip_carve_mp(&mp, mlen))) {
4272 4261 /* mp has already been freed by ip_carve_mp() */
4273 4262 BUMP_MIB(ill->ill_ip_mib, ipIfStatsOutFragFails);
4274 4263 ip_drop_output("FragFails: could not carve mp",
4275 4264 hmp0, ill);
4276 4265 if (hmp != NULL)
4277 4266 freeb(hmp);
4278 4267 freeb(hmp0);
4279 4268 ip1dbg(("ip_carve_mp: failed\n"));
4280 4269 return (ENOBUFS);
4281 4270 }
4282 4271 hmp0->b_cont = dmp;
4283 4272 /* Get the priority marking, if any */
4284 4273 hmp0->b_band = priority;
4285 4274
4286 4275 BUMP_MIB(ill->ill_ip_mib, ipIfStatsOutFragCreates);
4287 4276
4288 4277 error = postfragfn(hmp0, nce, ixaflags,
4289 4278 mlen + unfragmentable_len, xmit_hint, szone, nolzid,
4290 4279 ixa_cookie);
4291 4280 if (error != 0 && error != EWOULDBLOCK && hmp != NULL) {
4292 4281 /* No point in sending the other fragments */
4293 4282 BUMP_MIB(ill->ill_ip_mib, ipIfStatsOutFragFails);
4294 4283 ip_drop_output("FragFails: postfragfn failed",
4295 4284 hmp, ill);
4296 4285 freeb(hmp);
4297 4286 freemsg(mp);
4298 4287 return (error);
4299 4288 }
4300 4289 /* No need to redo state machine in loop */
4301 4290 ixaflags &= ~IXAF_REACH_CONF;
4302 4291
4303 4292 offset += mlen;
4304 4293 }
4305 4294 BUMP_MIB(ill->ill_ip_mib, ipIfStatsOutFragOKs);
4306 4295 return (error);
4307 4296 }
4308 4297
4309 4298 /*
4310 4299 * Add a fragment header to an IPv6 packet.
4311 4300 * Assumes that all the extension headers are contained in the first mblk.
4312 4301 *
4313 4302 * The fragment header is inserted after an hop-by-hop options header
4314 4303 * and after [an optional destinations header followed by] a routing header.
4315 4304 */
4316 4305 mblk_t *
4317 4306 ip_fraghdr_add_v6(mblk_t *mp, uint32_t ident, ip_xmit_attr_t *ixa)
4318 4307 {
4319 4308 ip6_t *ip6h = (ip6_t *)mp->b_rptr;
4320 4309 ip6_t *fip6h;
4321 4310 mblk_t *hmp;
4322 4311 ip6_frag_t *fraghdr;
4323 4312 size_t unfragmentable_len;
4324 4313 uint8_t nexthdr;
4325 4314 uint_t prev_nexthdr_offset;
4326 4315 uint8_t *ptr;
4327 4316 uint_t priority = mp->b_band;
4328 4317 ip_stack_t *ipst = ixa->ixa_ipst;
4329 4318
4330 4319 /*
4331 4320 * Determine the length of the unfragmentable portion of this
4332 4321 * datagram. This consists of the IPv6 header, a potential
4333 4322 * hop-by-hop options header, a potential pre-routing-header
4334 4323 * destination options header, and a potential routing header.
4335 4324 */
4336 4325 nexthdr = ip6h->ip6_nxt;
4337 4326 prev_nexthdr_offset = (uint8_t *)&ip6h->ip6_nxt - (uint8_t *)ip6h;
4338 4327 ptr = (uint8_t *)&ip6h[1];
4339 4328
4340 4329 if (nexthdr == IPPROTO_HOPOPTS) {
4341 4330 ip6_hbh_t *hbh_hdr;
4342 4331 uint_t hdr_len;
4343 4332
4344 4333 hbh_hdr = (ip6_hbh_t *)ptr;
4345 4334 hdr_len = 8 * (hbh_hdr->ip6h_len + 1);
4346 4335 nexthdr = hbh_hdr->ip6h_nxt;
4347 4336 prev_nexthdr_offset = (uint8_t *)&hbh_hdr->ip6h_nxt
4348 4337 - (uint8_t *)ip6h;
4349 4338 ptr += hdr_len;
4350 4339 }
4351 4340 if (nexthdr == IPPROTO_DSTOPTS) {
4352 4341 ip6_dest_t *dest_hdr;
4353 4342 uint_t hdr_len;
4354 4343
4355 4344 dest_hdr = (ip6_dest_t *)ptr;
4356 4345 if (dest_hdr->ip6d_nxt == IPPROTO_ROUTING) {
4357 4346 hdr_len = 8 * (dest_hdr->ip6d_len + 1);
4358 4347 nexthdr = dest_hdr->ip6d_nxt;
4359 4348 prev_nexthdr_offset = (uint8_t *)&dest_hdr->ip6d_nxt
4360 4349 - (uint8_t *)ip6h;
4361 4350 ptr += hdr_len;
4362 4351 }
4363 4352 }
4364 4353 if (nexthdr == IPPROTO_ROUTING) {
4365 4354 ip6_rthdr_t *rthdr;
4366 4355 uint_t hdr_len;
4367 4356
4368 4357 rthdr = (ip6_rthdr_t *)ptr;
4369 4358 nexthdr = rthdr->ip6r_nxt;
4370 4359 prev_nexthdr_offset = (uint8_t *)&rthdr->ip6r_nxt
4371 4360 - (uint8_t *)ip6h;
4372 4361 hdr_len = 8 * (rthdr->ip6r_len + 1);
4373 4362 ptr += hdr_len;
4374 4363 }
4375 4364 unfragmentable_len = (uint_t)(ptr - (uint8_t *)ip6h);
4376 4365
4377 4366 /*
4378 4367 * Allocate an mblk with enough room for the link-layer
4379 4368 * header, the unfragmentable part of the datagram, and the
4380 4369 * fragment header.
4381 4370 */
4382 4371 hmp = allocb_tmpl(unfragmentable_len + sizeof (ip6_frag_t) +
4383 4372 ipst->ips_ip_wroff_extra, mp);
4384 4373 if (hmp == NULL) {
4385 4374 ill_t *ill = ixa->ixa_nce->nce_ill;
4386 4375
4387 4376 BUMP_MIB(ill->ill_ip_mib, ipIfStatsOutDiscards);
4388 4377 ip_drop_output("ipIfStatsOutDiscards: allocb failure", mp, ill);
4389 4378 freemsg(mp);
4390 4379 return (NULL);
4391 4380 }
4392 4381 hmp->b_rptr += ipst->ips_ip_wroff_extra;
4393 4382 hmp->b_wptr = hmp->b_rptr + unfragmentable_len + sizeof (ip6_frag_t);
4394 4383
4395 4384 fip6h = (ip6_t *)hmp->b_rptr;
4396 4385 fraghdr = (ip6_frag_t *)(hmp->b_rptr + unfragmentable_len);
4397 4386
4398 4387 bcopy(ip6h, fip6h, unfragmentable_len);
4399 4388 fip6h->ip6_plen = htons(ntohs(fip6h->ip6_plen) + sizeof (ip6_frag_t));
4400 4389 hmp->b_rptr[prev_nexthdr_offset] = IPPROTO_FRAGMENT;
4401 4390
4402 4391 fraghdr->ip6f_nxt = nexthdr;
4403 4392 fraghdr->ip6f_reserved = 0;
4404 4393 fraghdr->ip6f_offlg = 0;
4405 4394 fraghdr->ip6f_ident = htonl(ident);
4406 4395
4407 4396 /* Get the priority marking, if any */
4408 4397 hmp->b_band = priority;
4409 4398
4410 4399 /*
4411 4400 * Move read ptr past unfragmentable portion, we don't want this part
4412 4401 * of the data in our fragments.
4413 4402 */
4414 4403 mp->b_rptr += unfragmentable_len;
4415 4404 hmp->b_cont = mp;
4416 4405 return (hmp);
4417 4406 }
4418 4407
4419 4408 /*
4420 4409 * Determine if the ill and multicast aspects of that packets
4421 4410 * "matches" the conn.
4422 4411 */
4423 4412 boolean_t
4424 4413 conn_wantpacket_v6(conn_t *connp, ip_recv_attr_t *ira, ip6_t *ip6h)
4425 4414 {
4426 4415 ill_t *ill = ira->ira_rill;
4427 4416 zoneid_t zoneid = ira->ira_zoneid;
4428 4417 uint_t in_ifindex;
4429 4418 in6_addr_t *v6dst_ptr = &ip6h->ip6_dst;
4430 4419 in6_addr_t *v6src_ptr = &ip6h->ip6_src;
4431 4420
4432 4421 /*
4433 4422 * conn_incoming_ifindex is set by IPV6_BOUND_IF and as link-local
4434 4423 * scopeid. This is used to limit
4435 4424 * unicast and multicast reception to conn_incoming_ifindex.
4436 4425 * conn_wantpacket_v6 is called both for unicast and
4437 4426 * multicast packets.
4438 4427 */
4439 4428 in_ifindex = connp->conn_incoming_ifindex;
4440 4429
4441 4430 /* mpathd can bind to the under IPMP interface, which we allow */
4442 4431 if (in_ifindex != 0 && in_ifindex != ill->ill_phyint->phyint_ifindex) {
4443 4432 if (!IS_UNDER_IPMP(ill))
4444 4433 return (B_FALSE);
4445 4434
4446 4435 if (in_ifindex != ipmp_ill_get_ipmp_ifindex(ill))
4447 4436 return (B_FALSE);
4448 4437 }
4449 4438
4450 4439 if (!IPCL_ZONE_MATCH(connp, zoneid))
4451 4440 return (B_FALSE);
4452 4441
4453 4442 if (!(ira->ira_flags & IRAF_MULTICAST))
4454 4443 return (B_TRUE);
4455 4444
4456 4445 if (connp->conn_multi_router)
4457 4446 return (B_TRUE);
4458 4447
4459 4448 if (ira->ira_protocol == IPPROTO_RSVP)
4460 4449 return (B_TRUE);
4461 4450
4462 4451 return (conn_hasmembers_ill_withsrc_v6(connp, v6dst_ptr, v6src_ptr,
4463 4452 ira->ira_ill));
4464 4453 }
4465 4454
4466 4455 /*
4467 4456 * pr_addr_dbg function provides the needed buffer space to call
4468 4457 * inet_ntop() function's 3rd argument. This function should be
4469 4458 * used by any kernel routine which wants to save INET6_ADDRSTRLEN
4470 4459 * stack buffer space in it's own stack frame. This function uses
4471 4460 * a buffer from it's own stack and prints the information.
4472 4461 * Example: pr_addr_dbg("func: no route for %s\n ", AF_INET, addr)
4473 4462 *
4474 4463 * Note: This function can call inet_ntop() once.
4475 4464 */
4476 4465 void
4477 4466 pr_addr_dbg(char *fmt1, int af, const void *addr)
4478 4467 {
4479 4468 char buf[INET6_ADDRSTRLEN];
4480 4469
4481 4470 if (fmt1 == NULL) {
4482 4471 ip0dbg(("pr_addr_dbg: Wrong arguments\n"));
4483 4472 return;
4484 4473 }
4485 4474
4486 4475 /*
4487 4476 * This does not compare debug level and just prints
4488 4477 * out. Thus it is the responsibility of the caller
4489 4478 * to check the appropriate debug-level before calling
4490 4479 * this function.
4491 4480 */
4492 4481 if (ip_debug > 0) {
4493 4482 printf(fmt1, inet_ntop(af, addr, buf, sizeof (buf)));
4494 4483 }
4495 4484
4496 4485
4497 4486 }
4498 4487
4499 4488
4500 4489 /*
4501 4490 * Return the length in bytes of the IPv6 headers (base header
4502 4491 * extension headers) that will be needed based on the
4503 4492 * ip_pkt_t structure passed by the caller.
4504 4493 *
4505 4494 * The returned length does not include the length of the upper level
4506 4495 * protocol (ULP) header.
4507 4496 */
4508 4497 int
4509 4498 ip_total_hdrs_len_v6(const ip_pkt_t *ipp)
4510 4499 {
4511 4500 int len;
4512 4501
4513 4502 len = IPV6_HDR_LEN;
4514 4503
4515 4504 /*
4516 4505 * If there's a security label here, then we ignore any hop-by-hop
4517 4506 * options the user may try to set.
4518 4507 */
4519 4508 if (ipp->ipp_fields & IPPF_LABEL_V6) {
4520 4509 uint_t hopoptslen;
4521 4510 /*
4522 4511 * Note that ipp_label_len_v6 is just the option - not
4523 4512 * the hopopts extension header. It also needs to be padded
4524 4513 * to a multiple of 8 bytes.
4525 4514 */
4526 4515 ASSERT(ipp->ipp_label_len_v6 != 0);
4527 4516 hopoptslen = ipp->ipp_label_len_v6 + sizeof (ip6_hbh_t);
4528 4517 hopoptslen = (hopoptslen + 7)/8 * 8;
4529 4518 len += hopoptslen;
4530 4519 } else if (ipp->ipp_fields & IPPF_HOPOPTS) {
4531 4520 ASSERT(ipp->ipp_hopoptslen != 0);
4532 4521 len += ipp->ipp_hopoptslen;
4533 4522 }
4534 4523
4535 4524 /*
4536 4525 * En-route destination options
4537 4526 * Only do them if there's a routing header as well
4538 4527 */
4539 4528 if ((ipp->ipp_fields & (IPPF_RTHDRDSTOPTS|IPPF_RTHDR)) ==
4540 4529 (IPPF_RTHDRDSTOPTS|IPPF_RTHDR)) {
4541 4530 ASSERT(ipp->ipp_rthdrdstoptslen != 0);
4542 4531 len += ipp->ipp_rthdrdstoptslen;
4543 4532 }
4544 4533 if (ipp->ipp_fields & IPPF_RTHDR) {
4545 4534 ASSERT(ipp->ipp_rthdrlen != 0);
4546 4535 len += ipp->ipp_rthdrlen;
4547 4536 }
4548 4537 if (ipp->ipp_fields & IPPF_DSTOPTS) {
4549 4538 ASSERT(ipp->ipp_dstoptslen != 0);
4550 4539 len += ipp->ipp_dstoptslen;
4551 4540 }
4552 4541 return (len);
4553 4542 }
4554 4543
4555 4544 /*
4556 4545 * All-purpose routine to build a header chain of an IPv6 header
4557 4546 * followed by any required extension headers and a proto header.
4558 4547 *
4559 4548 * The caller has to set the source and destination address as well as
4560 4549 * ip6_plen. The caller has to massage any routing header and compensate
4561 4550 * for the ULP pseudo-header checksum due to the source route.
4562 4551 *
4563 4552 * The extension headers will all be fully filled in.
4564 4553 */
4565 4554 void
4566 4555 ip_build_hdrs_v6(uchar_t *buf, uint_t buf_len, const ip_pkt_t *ipp,
4567 4556 uint8_t protocol, uint32_t flowinfo)
4568 4557 {
4569 4558 uint8_t *nxthdr_ptr;
4570 4559 uint8_t *cp;
4571 4560 ip6_t *ip6h = (ip6_t *)buf;
4572 4561
4573 4562 /* Initialize IPv6 header */
4574 4563 ip6h->ip6_vcf =
4575 4564 (IPV6_DEFAULT_VERS_AND_FLOW & IPV6_VERS_AND_FLOW_MASK) |
4576 4565 (flowinfo & ~IPV6_VERS_AND_FLOW_MASK);
4577 4566
4578 4567 if (ipp->ipp_fields & IPPF_TCLASS) {
4579 4568 /* Overrides the class part of flowinfo */
4580 4569 ip6h->ip6_vcf = IPV6_TCLASS_FLOW(ip6h->ip6_vcf,
4581 4570 ipp->ipp_tclass);
4582 4571 }
4583 4572
4584 4573 if (ipp->ipp_fields & IPPF_HOPLIMIT)
4585 4574 ip6h->ip6_hops = ipp->ipp_hoplimit;
4586 4575 else
4587 4576 ip6h->ip6_hops = ipp->ipp_unicast_hops;
4588 4577
4589 4578 if ((ipp->ipp_fields & IPPF_ADDR) &&
4590 4579 !IN6_IS_ADDR_V4MAPPED(&ipp->ipp_addr))
4591 4580 ip6h->ip6_src = ipp->ipp_addr;
4592 4581
4593 4582 nxthdr_ptr = (uint8_t *)&ip6h->ip6_nxt;
4594 4583 cp = (uint8_t *)&ip6h[1];
4595 4584 /*
4596 4585 * Here's where we have to start stringing together
4597 4586 * any extension headers in the right order:
4598 4587 * Hop-by-hop, destination, routing, and final destination opts.
4599 4588 */
4600 4589 /*
4601 4590 * If there's a security label here, then we ignore any hop-by-hop
4602 4591 * options the user may try to set.
4603 4592 */
4604 4593 if (ipp->ipp_fields & IPPF_LABEL_V6) {
4605 4594 /*
4606 4595 * Hop-by-hop options with the label.
4607 4596 * Note that ipp_label_v6 is just the option - not
4608 4597 * the hopopts extension header. It also needs to be padded
4609 4598 * to a multiple of 8 bytes.
4610 4599 */
4611 4600 ip6_hbh_t *hbh = (ip6_hbh_t *)cp;
4612 4601 uint_t hopoptslen;
4613 4602 uint_t padlen;
4614 4603
4615 4604 padlen = ipp->ipp_label_len_v6 + sizeof (ip6_hbh_t);
4616 4605 hopoptslen = (padlen + 7)/8 * 8;
4617 4606 padlen = hopoptslen - padlen;
4618 4607
4619 4608 *nxthdr_ptr = IPPROTO_HOPOPTS;
4620 4609 nxthdr_ptr = &hbh->ip6h_nxt;
4621 4610 hbh->ip6h_len = hopoptslen/8 - 1;
4622 4611 cp += sizeof (ip6_hbh_t);
4623 4612 bcopy(ipp->ipp_label_v6, cp, ipp->ipp_label_len_v6);
4624 4613 cp += ipp->ipp_label_len_v6;
4625 4614
4626 4615 ASSERT(padlen <= 7);
4627 4616 switch (padlen) {
4628 4617 case 0:
4629 4618 break;
4630 4619 case 1:
4631 4620 cp[0] = IP6OPT_PAD1;
4632 4621 break;
4633 4622 default:
4634 4623 cp[0] = IP6OPT_PADN;
4635 4624 cp[1] = padlen - 2;
4636 4625 bzero(&cp[2], padlen - 2);
4637 4626 break;
4638 4627 }
4639 4628 cp += padlen;
4640 4629 } else if (ipp->ipp_fields & IPPF_HOPOPTS) {
4641 4630 /* Hop-by-hop options */
4642 4631 ip6_hbh_t *hbh = (ip6_hbh_t *)cp;
4643 4632
4644 4633 *nxthdr_ptr = IPPROTO_HOPOPTS;
4645 4634 nxthdr_ptr = &hbh->ip6h_nxt;
4646 4635
4647 4636 bcopy(ipp->ipp_hopopts, cp, ipp->ipp_hopoptslen);
4648 4637 cp += ipp->ipp_hopoptslen;
4649 4638 }
4650 4639 /*
4651 4640 * En-route destination options
4652 4641 * Only do them if there's a routing header as well
4653 4642 */
4654 4643 if ((ipp->ipp_fields & (IPPF_RTHDRDSTOPTS|IPPF_RTHDR)) ==
4655 4644 (IPPF_RTHDRDSTOPTS|IPPF_RTHDR)) {
4656 4645 ip6_dest_t *dst = (ip6_dest_t *)cp;
4657 4646
4658 4647 *nxthdr_ptr = IPPROTO_DSTOPTS;
4659 4648 nxthdr_ptr = &dst->ip6d_nxt;
4660 4649
4661 4650 bcopy(ipp->ipp_rthdrdstopts, cp, ipp->ipp_rthdrdstoptslen);
4662 4651 cp += ipp->ipp_rthdrdstoptslen;
4663 4652 }
4664 4653 /*
4665 4654 * Routing header next
4666 4655 */
4667 4656 if (ipp->ipp_fields & IPPF_RTHDR) {
4668 4657 ip6_rthdr_t *rt = (ip6_rthdr_t *)cp;
4669 4658
4670 4659 *nxthdr_ptr = IPPROTO_ROUTING;
4671 4660 nxthdr_ptr = &rt->ip6r_nxt;
4672 4661
4673 4662 bcopy(ipp->ipp_rthdr, cp, ipp->ipp_rthdrlen);
4674 4663 cp += ipp->ipp_rthdrlen;
4675 4664 }
4676 4665 /*
4677 4666 * Do ultimate destination options
4678 4667 */
4679 4668 if (ipp->ipp_fields & IPPF_DSTOPTS) {
4680 4669 ip6_dest_t *dest = (ip6_dest_t *)cp;
4681 4670
4682 4671 *nxthdr_ptr = IPPROTO_DSTOPTS;
4683 4672 nxthdr_ptr = &dest->ip6d_nxt;
4684 4673
4685 4674 bcopy(ipp->ipp_dstopts, cp, ipp->ipp_dstoptslen);
4686 4675 cp += ipp->ipp_dstoptslen;
4687 4676 }
4688 4677 /*
4689 4678 * Now set the last header pointer to the proto passed in
4690 4679 */
4691 4680 *nxthdr_ptr = protocol;
4692 4681 ASSERT((int)(cp - buf) == buf_len);
4693 4682 }
4694 4683
4695 4684 /*
4696 4685 * Return a pointer to the routing header extension header
4697 4686 * in the IPv6 header(s) chain passed in.
4698 4687 * If none found, return NULL
4699 4688 * Assumes that all extension headers are in same mblk as the v6 header
4700 4689 */
4701 4690 ip6_rthdr_t *
4702 4691 ip_find_rthdr_v6(ip6_t *ip6h, uint8_t *endptr)
4703 4692 {
4704 4693 ip6_dest_t *desthdr;
4705 4694 ip6_frag_t *fraghdr;
4706 4695 uint_t hdrlen;
4707 4696 uint8_t nexthdr;
4708 4697 uint8_t *ptr = (uint8_t *)&ip6h[1];
4709 4698
4710 4699 if (ip6h->ip6_nxt == IPPROTO_ROUTING)
4711 4700 return ((ip6_rthdr_t *)ptr);
4712 4701
4713 4702 /*
4714 4703 * The routing header will precede all extension headers
4715 4704 * other than the hop-by-hop and destination options
4716 4705 * extension headers, so if we see anything other than those,
4717 4706 * we're done and didn't find it.
4718 4707 * We could see a destination options header alone but no
4719 4708 * routing header, in which case we'll return NULL as soon as
4720 4709 * we see anything after that.
4721 4710 * Hop-by-hop and destination option headers are identical,
4722 4711 * so we can use either one we want as a template.
4723 4712 */
4724 4713 nexthdr = ip6h->ip6_nxt;
4725 4714 while (ptr < endptr) {
4726 4715 /* Is there enough left for len + nexthdr? */
4727 4716 if (ptr + MIN_EHDR_LEN > endptr)
4728 4717 return (NULL);
4729 4718
4730 4719 switch (nexthdr) {
4731 4720 case IPPROTO_HOPOPTS:
4732 4721 case IPPROTO_DSTOPTS:
4733 4722 /* Assumes the headers are identical for hbh and dst */
4734 4723 desthdr = (ip6_dest_t *)ptr;
4735 4724 hdrlen = 8 * (desthdr->ip6d_len + 1);
4736 4725 nexthdr = desthdr->ip6d_nxt;
4737 4726 break;
4738 4727
4739 4728 case IPPROTO_ROUTING:
4740 4729 return ((ip6_rthdr_t *)ptr);
4741 4730
4742 4731 case IPPROTO_FRAGMENT:
4743 4732 fraghdr = (ip6_frag_t *)ptr;
4744 4733 hdrlen = sizeof (ip6_frag_t);
4745 4734 nexthdr = fraghdr->ip6f_nxt;
4746 4735 break;
4747 4736
4748 4737 default:
4749 4738 return (NULL);
4750 4739 }
4751 4740 ptr += hdrlen;
4752 4741 }
4753 4742 return (NULL);
4754 4743 }
4755 4744
4756 4745 /*
4757 4746 * Called for source-routed packets originating on this node.
4758 4747 * Manipulates the original routing header by moving every entry up
4759 4748 * one slot, placing the first entry in the v6 header's v6_dst field,
4760 4749 * and placing the ultimate destination in the routing header's last
4761 4750 * slot.
4762 4751 *
4763 4752 * Returns the checksum diference between the ultimate destination
4764 4753 * (last hop in the routing header when the packet is sent) and
4765 4754 * the first hop (ip6_dst when the packet is sent)
4766 4755 */
4767 4756 /* ARGSUSED2 */
4768 4757 uint32_t
4769 4758 ip_massage_options_v6(ip6_t *ip6h, ip6_rthdr_t *rth, netstack_t *ns)
4770 4759 {
4771 4760 uint_t numaddr;
4772 4761 uint_t i;
4773 4762 in6_addr_t *addrptr;
4774 4763 in6_addr_t tmp;
4775 4764 ip6_rthdr0_t *rthdr = (ip6_rthdr0_t *)rth;
4776 4765 uint32_t cksm;
4777 4766 uint32_t addrsum = 0;
4778 4767 uint16_t *ptr;
4779 4768
4780 4769 /*
4781 4770 * Perform any processing needed for source routing.
4782 4771 * We know that all extension headers will be in the same mblk
4783 4772 * as the IPv6 header.
4784 4773 */
4785 4774
4786 4775 /*
4787 4776 * If no segments left in header, or the header length field is zero,
4788 4777 * don't move hop addresses around;
4789 4778 * Checksum difference is zero.
4790 4779 */
4791 4780 if ((rthdr->ip6r0_segleft == 0) || (rthdr->ip6r0_len == 0))
4792 4781 return (0);
4793 4782
4794 4783 ptr = (uint16_t *)&ip6h->ip6_dst;
4795 4784 cksm = 0;
4796 4785 for (i = 0; i < (sizeof (in6_addr_t) / sizeof (uint16_t)); i++) {
4797 4786 cksm += ptr[i];
4798 4787 }
4799 4788 cksm = (cksm & 0xFFFF) + (cksm >> 16);
4800 4789
4801 4790 /*
4802 4791 * Here's where the fun begins - we have to
4803 4792 * move all addresses up one spot, take the
4804 4793 * first hop and make it our first ip6_dst,
4805 4794 * and place the ultimate destination in the
4806 4795 * newly-opened last slot.
4807 4796 */
4808 4797 addrptr = (in6_addr_t *)((char *)rthdr + sizeof (*rthdr));
4809 4798 numaddr = rthdr->ip6r0_len / 2;
4810 4799 tmp = *addrptr;
4811 4800 for (i = 0; i < (numaddr - 1); addrptr++, i++) {
4812 4801 *addrptr = addrptr[1];
4813 4802 }
4814 4803 *addrptr = ip6h->ip6_dst;
4815 4804 ip6h->ip6_dst = tmp;
4816 4805
4817 4806 /*
4818 4807 * From the checksummed ultimate destination subtract the checksummed
4819 4808 * current ip6_dst (the first hop address). Return that number.
4820 4809 * (In the v4 case, the second part of this is done in each routine
4821 4810 * that calls ip_massage_options(). We do it all in this one place
4822 4811 * for v6).
4823 4812 */
4824 4813 ptr = (uint16_t *)&ip6h->ip6_dst;
4825 4814 for (i = 0; i < (sizeof (in6_addr_t) / sizeof (uint16_t)); i++) {
4826 4815 addrsum += ptr[i];
4827 4816 }
4828 4817 cksm -= ((addrsum >> 16) + (addrsum & 0xFFFF));
4829 4818 if ((int)cksm < 0)
4830 4819 cksm--;
4831 4820 cksm = (cksm & 0xFFFF) + (cksm >> 16);
4832 4821
4833 4822 return (cksm);
4834 4823 }
4835 4824
4836 4825 void
4837 4826 *ip6_kstat_init(netstackid_t stackid, ip6_stat_t *ip6_statisticsp)
4838 4827 {
4839 4828 kstat_t *ksp;
4840 4829
4841 4830 ip6_stat_t template = {
4842 4831 { "ip6_udp_fannorm", KSTAT_DATA_UINT64 },
4843 4832 { "ip6_udp_fanmb", KSTAT_DATA_UINT64 },
4844 4833 { "ip6_recv_pullup", KSTAT_DATA_UINT64 },
4845 4834 { "ip6_db_ref", KSTAT_DATA_UINT64 },
4846 4835 { "ip6_notaligned", KSTAT_DATA_UINT64 },
4847 4836 { "ip6_multimblk", KSTAT_DATA_UINT64 },
4848 4837 { "ipsec_proto_ahesp", KSTAT_DATA_UINT64 },
4849 4838 { "ip6_out_sw_cksum", KSTAT_DATA_UINT64 },
4850 4839 { "ip6_out_sw_cksum_bytes", KSTAT_DATA_UINT64 },
4851 4840 { "ip6_in_sw_cksum", KSTAT_DATA_UINT64 },
4852 4841 { "ip6_tcp_in_full_hw_cksum_err", KSTAT_DATA_UINT64 },
4853 4842 { "ip6_tcp_in_part_hw_cksum_err", KSTAT_DATA_UINT64 },
4854 4843 { "ip6_tcp_in_sw_cksum_err", KSTAT_DATA_UINT64 },
4855 4844 { "ip6_udp_in_full_hw_cksum_err", KSTAT_DATA_UINT64 },
4856 4845 { "ip6_udp_in_part_hw_cksum_err", KSTAT_DATA_UINT64 },
4857 4846 { "ip6_udp_in_sw_cksum_err", KSTAT_DATA_UINT64 },
4858 4847 };
4859 4848 ksp = kstat_create_netstack("ip", 0, "ip6stat", "net",
4860 4849 KSTAT_TYPE_NAMED, sizeof (template) / sizeof (kstat_named_t),
4861 4850 KSTAT_FLAG_VIRTUAL, stackid);
4862 4851
4863 4852 if (ksp == NULL)
4864 4853 return (NULL);
4865 4854
4866 4855 bcopy(&template, ip6_statisticsp, sizeof (template));
4867 4856 ksp->ks_data = (void *)ip6_statisticsp;
4868 4857 ksp->ks_private = (void *)(uintptr_t)stackid;
4869 4858
4870 4859 kstat_install(ksp);
4871 4860 return (ksp);
4872 4861 }
4873 4862
4874 4863 void
4875 4864 ip6_kstat_fini(netstackid_t stackid, kstat_t *ksp)
4876 4865 {
4877 4866 if (ksp != NULL) {
4878 4867 ASSERT(stackid == (netstackid_t)(uintptr_t)ksp->ks_private);
4879 4868 kstat_delete_netstack(ksp, stackid);
4880 4869 }
4881 4870 }
4882 4871
4883 4872 /*
4884 4873 * The following two functions set and get the value for the
4885 4874 * IPV6_SRC_PREFERENCES socket option.
4886 4875 */
4887 4876 int
4888 4877 ip6_set_src_preferences(ip_xmit_attr_t *ixa, uint32_t prefs)
4889 4878 {
4890 4879 /*
4891 4880 * We only support preferences that are covered by
4892 4881 * IPV6_PREFER_SRC_MASK.
4893 4882 */
4894 4883 if (prefs & ~IPV6_PREFER_SRC_MASK)
4895 4884 return (EINVAL);
4896 4885
4897 4886 /*
4898 4887 * Look for conflicting preferences or default preferences. If
4899 4888 * both bits of a related pair are clear, the application wants the
4900 4889 * system's default value for that pair. Both bits in a pair can't
4901 4890 * be set.
4902 4891 */
4903 4892 if ((prefs & IPV6_PREFER_SRC_MIPMASK) == 0) {
4904 4893 prefs |= IPV6_PREFER_SRC_MIPDEFAULT;
4905 4894 } else if ((prefs & IPV6_PREFER_SRC_MIPMASK) ==
4906 4895 IPV6_PREFER_SRC_MIPMASK) {
4907 4896 return (EINVAL);
4908 4897 }
4909 4898 if ((prefs & IPV6_PREFER_SRC_TMPMASK) == 0) {
4910 4899 prefs |= IPV6_PREFER_SRC_TMPDEFAULT;
4911 4900 } else if ((prefs & IPV6_PREFER_SRC_TMPMASK) ==
4912 4901 IPV6_PREFER_SRC_TMPMASK) {
4913 4902 return (EINVAL);
4914 4903 }
4915 4904 if ((prefs & IPV6_PREFER_SRC_CGAMASK) == 0) {
4916 4905 prefs |= IPV6_PREFER_SRC_CGADEFAULT;
4917 4906 } else if ((prefs & IPV6_PREFER_SRC_CGAMASK) ==
4918 4907 IPV6_PREFER_SRC_CGAMASK) {
4919 4908 return (EINVAL);
4920 4909 }
4921 4910
4922 4911 ixa->ixa_src_preferences = prefs;
4923 4912 return (0);
4924 4913 }
4925 4914
4926 4915 size_t
4927 4916 ip6_get_src_preferences(ip_xmit_attr_t *ixa, uint32_t *val)
4928 4917 {
4929 4918 *val = ixa->ixa_src_preferences;
4930 4919 return (sizeof (ixa->ixa_src_preferences));
4931 4920 }
4932 4921
4933 4922 /*
4934 4923 * Get the size of the IP options (including the IP headers size)
4935 4924 * without including the AH header's size. If till_ah is B_FALSE,
4936 4925 * and if AH header is present, dest options beyond AH header will
4937 4926 * also be included in the returned size.
4938 4927 */
4939 4928 int
4940 4929 ipsec_ah_get_hdr_size_v6(mblk_t *mp, boolean_t till_ah)
4941 4930 {
4942 4931 ip6_t *ip6h;
4943 4932 uint8_t nexthdr;
4944 4933 uint8_t *whereptr;
4945 4934 ip6_hbh_t *hbhhdr;
4946 4935 ip6_dest_t *dsthdr;
4947 4936 ip6_rthdr_t *rthdr;
4948 4937 int ehdrlen;
4949 4938 int size;
4950 4939 ah_t *ah;
4951 4940
4952 4941 ip6h = (ip6_t *)mp->b_rptr;
4953 4942 size = IPV6_HDR_LEN;
4954 4943 nexthdr = ip6h->ip6_nxt;
4955 4944 whereptr = (uint8_t *)&ip6h[1];
4956 4945 for (;;) {
4957 4946 /* Assume IP has already stripped it */
4958 4947 ASSERT(nexthdr != IPPROTO_FRAGMENT);
4959 4948 switch (nexthdr) {
4960 4949 case IPPROTO_HOPOPTS:
4961 4950 hbhhdr = (ip6_hbh_t *)whereptr;
4962 4951 nexthdr = hbhhdr->ip6h_nxt;
4963 4952 ehdrlen = 8 * (hbhhdr->ip6h_len + 1);
4964 4953 break;
4965 4954 case IPPROTO_DSTOPTS:
4966 4955 dsthdr = (ip6_dest_t *)whereptr;
4967 4956 nexthdr = dsthdr->ip6d_nxt;
4968 4957 ehdrlen = 8 * (dsthdr->ip6d_len + 1);
4969 4958 break;
4970 4959 case IPPROTO_ROUTING:
4971 4960 rthdr = (ip6_rthdr_t *)whereptr;
4972 4961 nexthdr = rthdr->ip6r_nxt;
4973 4962 ehdrlen = 8 * (rthdr->ip6r_len + 1);
4974 4963 break;
4975 4964 default :
4976 4965 if (till_ah) {
4977 4966 ASSERT(nexthdr == IPPROTO_AH);
4978 4967 return (size);
4979 4968 }
4980 4969 /*
4981 4970 * If we don't have a AH header to traverse,
4982 4971 * return now. This happens normally for
4983 4972 * outbound datagrams where we have not inserted
4984 4973 * the AH header.
4985 4974 */
4986 4975 if (nexthdr != IPPROTO_AH) {
4987 4976 return (size);
4988 4977 }
4989 4978
4990 4979 /*
4991 4980 * We don't include the AH header's size
4992 4981 * to be symmetrical with other cases where
4993 4982 * we either don't have a AH header (outbound)
4994 4983 * or peek into the AH header yet (inbound and
4995 4984 * not pulled up yet).
4996 4985 */
4997 4986 ah = (ah_t *)whereptr;
4998 4987 nexthdr = ah->ah_nexthdr;
4999 4988 ehdrlen = (ah->ah_length << 2) + 8;
5000 4989
5001 4990 if (nexthdr == IPPROTO_DSTOPTS) {
5002 4991 if (whereptr + ehdrlen >= mp->b_wptr) {
5003 4992 /*
5004 4993 * The destination options header
5005 4994 * is not part of the first mblk.
5006 4995 */
5007 4996 whereptr = mp->b_cont->b_rptr;
5008 4997 } else {
5009 4998 whereptr += ehdrlen;
5010 4999 }
5011 5000
5012 5001 dsthdr = (ip6_dest_t *)whereptr;
5013 5002 ehdrlen = 8 * (dsthdr->ip6d_len + 1);
5014 5003 size += ehdrlen;
5015 5004 }
5016 5005 return (size);
5017 5006 }
5018 5007 whereptr += ehdrlen;
5019 5008 size += ehdrlen;
5020 5009 }
5021 5010 }
5022 5011
5023 5012 /*
5024 5013 * Utility routine that checks if `v6srcp' is a valid address on underlying
5025 5014 * interface `ill'. If `ipifp' is non-NULL, it's set to a held ipif
5026 5015 * associated with `v6srcp' on success. NOTE: if this is not called from
5027 5016 * inside the IPSQ (ill_g_lock is not held), `ill' may be removed from the
5028 5017 * group during or after this lookup.
5029 5018 */
5030 5019 boolean_t
5031 5020 ipif_lookup_testaddr_v6(ill_t *ill, const in6_addr_t *v6srcp, ipif_t **ipifp)
5032 5021 {
5033 5022 ipif_t *ipif;
5034 5023
5035 5024
5036 5025 ipif = ipif_lookup_addr_exact_v6(v6srcp, ill, ill->ill_ipst);
5037 5026 if (ipif != NULL) {
5038 5027 if (ipifp != NULL)
5039 5028 *ipifp = ipif;
5040 5029 else
5041 5030 ipif_refrele(ipif);
5042 5031 return (B_TRUE);
5043 5032 }
5044 5033
5045 5034 if (ip_debug > 2) {
5046 5035 pr_addr_dbg("ipif_lookup_testaddr_v6: cannot find ipif for "
5047 5036 "src %s\n", AF_INET6, v6srcp);
5048 5037 }
5049 5038 return (B_FALSE);
5050 5039 }
|
↓ open down ↓ |
4293 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX