Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/netinet6/icmp6.c
39475 views
1
/*-
2
* SPDX-License-Identifier: BSD-3-Clause
3
*
4
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
* 3. Neither the name of the project nor the names of its contributors
16
* may be used to endorse or promote products derived from this software
17
* without specific prior written permission.
18
*
19
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
* SUCH DAMAGE.
30
*
31
* $KAME: icmp6.c,v 1.211 2001/04/04 05:56:20 itojun Exp $
32
*/
33
34
/*-
35
* Copyright (c) 1982, 1986, 1988, 1993
36
* The Regents of the University of California. All rights reserved.
37
*
38
* Redistribution and use in source and binary forms, with or without
39
* modification, are permitted provided that the following conditions
40
* are met:
41
* 1. Redistributions of source code must retain the above copyright
42
* notice, this list of conditions and the following disclaimer.
43
* 2. Redistributions in binary form must reproduce the above copyright
44
* notice, this list of conditions and the following disclaimer in the
45
* documentation and/or other materials provided with the distribution.
46
* 3. Neither the name of the University nor the names of its contributors
47
* may be used to endorse or promote products derived from this software
48
* without specific prior written permission.
49
*
50
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60
* SUCH DAMAGE.
61
*/
62
63
#include <sys/cdefs.h>
64
#define MBUF_PRIVATE /* XXXRW: Optimisation tries to avoid M_EXT mbufs */
65
66
#include "opt_inet.h"
67
#include "opt_inet6.h"
68
69
#include <sys/param.h>
70
#include <sys/domain.h>
71
#include <sys/jail.h>
72
#include <sys/kernel.h>
73
#include <sys/lock.h>
74
#include <sys/malloc.h>
75
#include <sys/mbuf.h>
76
#include <sys/proc.h>
77
#include <sys/protosw.h>
78
#include <sys/signalvar.h>
79
#include <sys/socket.h>
80
#include <sys/socketvar.h>
81
#include <sys/sx.h>
82
#include <sys/syslog.h>
83
#include <sys/systm.h>
84
#include <sys/time.h>
85
86
#include <net/if.h>
87
#include <net/if_var.h>
88
#include <net/if_dl.h>
89
#include <net/if_llatbl.h>
90
#include <net/if_private.h>
91
#include <net/if_types.h>
92
#include <net/route.h>
93
#include <net/route/route_ctl.h>
94
#include <net/route/nhop.h>
95
#include <net/vnet.h>
96
97
#include <netinet/in.h>
98
#include <netinet/in_pcb.h>
99
#include <netinet/in_var.h>
100
#include <netinet/ip6.h>
101
#include <netinet/icmp6.h>
102
#include <netinet/tcp_var.h>
103
104
#include <netinet6/in6_fib.h>
105
#include <netinet6/in6_ifattach.h>
106
#include <netinet6/in6_pcb.h>
107
#include <netinet6/ip6_var.h>
108
#include <netinet6/scope6_var.h>
109
#include <netinet6/mld6_var.h>
110
#include <netinet6/nd6.h>
111
#include <netinet6/send.h>
112
113
extern ip6proto_ctlinput_t *ip6_ctlprotox[];
114
115
VNET_PCPUSTAT_DEFINE(struct icmp6stat, icmp6stat);
116
VNET_PCPUSTAT_SYSINIT(icmp6stat);
117
SYSCTL_VNET_PCPUSTAT(_net_inet6_icmp6, ICMPV6CTL_STATS, stats,
118
struct icmp6stat, icmp6stat,
119
"ICMPv6 statistics (struct icmp6stat, netinet/icmp6.h)");
120
121
#ifdef VIMAGE
122
VNET_PCPUSTAT_SYSUNINIT(icmp6stat);
123
#endif /* VIMAGE */
124
125
VNET_DEFINE_STATIC(int, icmp6_rediraccept) = 1;
126
#define V_icmp6_rediraccept VNET(icmp6_rediraccept)
127
SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_REDIRACCEPT, rediraccept,
128
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(icmp6_rediraccept), 0,
129
"Accept ICMPv6 redirect messages");
130
131
VNET_DEFINE_STATIC(int, icmp6_redirtimeout) = 10 * 60; /* 10 minutes */
132
#define V_icmp6_redirtimeout VNET(icmp6_redirtimeout)
133
SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_REDIRTIMEOUT, redirtimeout,
134
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(icmp6_redirtimeout), 0,
135
"Delay in seconds before expiring redirect route");
136
137
VNET_DEFINE_STATIC(int, icmp6_nodeinfo) = 0;
138
#define V_icmp6_nodeinfo VNET(icmp6_nodeinfo)
139
SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_NODEINFO, nodeinfo,
140
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(icmp6_nodeinfo), 0,
141
"Mask of enabled RFC4620 node information query types");
142
143
VNET_DECLARE(struct inpcbinfo, ripcbinfo);
144
#define V_ripcbinfo VNET(ripcbinfo)
145
146
VNET_DECLARE(int, rip_bind_all_fibs);
147
#define V_rip_bind_all_fibs VNET(rip_bind_all_fibs)
148
149
static void icmp6_errcount(int, int);
150
static int icmp6_rip6_input(struct mbuf **, int);
151
static void icmp6_reflect(struct mbuf *, size_t);
152
static const char *icmp6_redirect_diag(struct in6_addr *,
153
struct in6_addr *, struct in6_addr *);
154
static struct mbuf *ni6_input(struct mbuf *, int, struct prison *);
155
static struct mbuf *ni6_nametodns(const char *, int, int);
156
static int ni6_dnsmatch(const char *, int, const char *, int);
157
static int ni6_addrs(struct icmp6_nodeinfo *, struct mbuf *,
158
struct ifnet **, struct in6_addr *);
159
static int ni6_store_addrs(struct icmp6_nodeinfo *, struct icmp6_nodeinfo *,
160
struct ifnet *, int);
161
static int icmp6_notify_error(struct mbuf **, int, int);
162
static void icmp6_mtudisc_update(struct ip6ctlparam *ip6cp);
163
164
/*
165
* Kernel module interface for updating icmp6stat. The argument is an index
166
* into icmp6stat treated as an array of u_quad_t. While this encodes the
167
* general layout of icmp6stat into the caller, it doesn't encode its
168
* location, so that future changes to add, for example, per-CPU stats
169
* support won't cause binary compatibility problems for kernel modules.
170
*/
171
void
172
kmod_icmp6stat_inc(int statnum)
173
{
174
175
counter_u64_add(VNET(icmp6stat)[statnum], 1);
176
}
177
178
static void
179
icmp6_errcount(int type, int code)
180
{
181
switch (type) {
182
case ICMP6_DST_UNREACH:
183
switch (code) {
184
case ICMP6_DST_UNREACH_NOROUTE:
185
ICMP6STAT_INC(icp6s_odst_unreach_noroute);
186
return;
187
case ICMP6_DST_UNREACH_ADMIN:
188
ICMP6STAT_INC(icp6s_odst_unreach_admin);
189
return;
190
case ICMP6_DST_UNREACH_BEYONDSCOPE:
191
ICMP6STAT_INC(icp6s_odst_unreach_beyondscope);
192
return;
193
case ICMP6_DST_UNREACH_ADDR:
194
ICMP6STAT_INC(icp6s_odst_unreach_addr);
195
return;
196
case ICMP6_DST_UNREACH_NOPORT:
197
ICMP6STAT_INC(icp6s_odst_unreach_noport);
198
return;
199
}
200
break;
201
case ICMP6_PACKET_TOO_BIG:
202
ICMP6STAT_INC(icp6s_opacket_too_big);
203
return;
204
case ICMP6_TIME_EXCEEDED:
205
switch (code) {
206
case ICMP6_TIME_EXCEED_TRANSIT:
207
ICMP6STAT_INC(icp6s_otime_exceed_transit);
208
return;
209
case ICMP6_TIME_EXCEED_REASSEMBLY:
210
ICMP6STAT_INC(icp6s_otime_exceed_reassembly);
211
return;
212
}
213
break;
214
case ICMP6_PARAM_PROB:
215
switch (code) {
216
case ICMP6_PARAMPROB_HEADER:
217
ICMP6STAT_INC(icp6s_oparamprob_header);
218
return;
219
case ICMP6_PARAMPROB_NEXTHEADER:
220
ICMP6STAT_INC(icp6s_oparamprob_nextheader);
221
return;
222
case ICMP6_PARAMPROB_OPTION:
223
ICMP6STAT_INC(icp6s_oparamprob_option);
224
return;
225
}
226
break;
227
case ND_REDIRECT:
228
ICMP6STAT_INC(icp6s_oredirect);
229
return;
230
}
231
ICMP6STAT_INC(icp6s_ounknown);
232
}
233
234
/*
235
* A wrapper function for icmp6_error() necessary when the erroneous packet
236
* may not contain enough scope zone information.
237
*/
238
void
239
icmp6_error2(struct mbuf *m, int type, int code, int param,
240
struct ifnet *ifp)
241
{
242
struct ip6_hdr *ip6;
243
244
if (ifp == NULL)
245
return;
246
247
if (m->m_len < sizeof(struct ip6_hdr)) {
248
m = m_pullup(m, sizeof(struct ip6_hdr));
249
if (m == NULL) {
250
IP6STAT_INC(ip6s_exthdrtoolong);
251
return;
252
}
253
}
254
ip6 = mtod(m, struct ip6_hdr *);
255
256
if (in6_setscope(&ip6->ip6_src, ifp, NULL) != 0)
257
return;
258
if (in6_setscope(&ip6->ip6_dst, ifp, NULL) != 0)
259
return;
260
261
icmp6_error(m, type, code, param);
262
}
263
264
/*
265
* Generate an error packet of type error in response to bad IP6 packet.
266
*/
267
void
268
icmp6_error(struct mbuf *m, int type, int code, int param)
269
{
270
struct ip6_hdr *oip6, *nip6;
271
struct icmp6_hdr *icmp6;
272
struct epoch_tracker et;
273
u_int preplen;
274
int off;
275
int nxt;
276
277
ICMP6STAT_INC(icp6s_error);
278
279
/* count per-type-code statistics */
280
icmp6_errcount(type, code);
281
282
#ifdef M_DECRYPTED /*not openbsd*/
283
if (m->m_flags & M_DECRYPTED) {
284
ICMP6STAT_INC(icp6s_canterror);
285
goto freeit;
286
}
287
#endif
288
289
if (m->m_len < sizeof(struct ip6_hdr)) {
290
m = m_pullup(m, sizeof(struct ip6_hdr));
291
if (m == NULL) {
292
IP6STAT_INC(ip6s_exthdrtoolong);
293
return;
294
}
295
}
296
oip6 = mtod(m, struct ip6_hdr *);
297
298
/*
299
* If the destination address of the erroneous packet is a multicast
300
* address, or the packet was sent using link-layer multicast,
301
* we should basically suppress sending an error (RFC 2463, Section
302
* 2.4).
303
* We have two exceptions (the item e.2 in that section):
304
* - the Packet Too Big message can be sent for path MTU discovery.
305
* - the Parameter Problem Message that can be allowed an icmp6 error
306
* in the option type field. This check has been done in
307
* ip6_unknown_opt(), so we can just check the type and code.
308
*/
309
if ((m->m_flags & (M_BCAST|M_MCAST) ||
310
IN6_IS_ADDR_MULTICAST(&oip6->ip6_dst)) &&
311
(type != ICMP6_PACKET_TOO_BIG &&
312
(type != ICMP6_PARAM_PROB ||
313
code != ICMP6_PARAMPROB_OPTION)))
314
goto freeit;
315
316
/*
317
* RFC 2463, 2.4 (e.5): source address check.
318
* XXX: the case of anycast source?
319
*/
320
if (IN6_IS_ADDR_UNSPECIFIED(&oip6->ip6_src) ||
321
IN6_IS_ADDR_MULTICAST(&oip6->ip6_src))
322
goto freeit;
323
324
/*
325
* If we are about to send ICMPv6 against ICMPv6 error/redirect,
326
* don't do it.
327
*/
328
nxt = -1;
329
off = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt);
330
if (off >= 0 && nxt == IPPROTO_ICMPV6) {
331
struct icmp6_hdr *icp;
332
333
if (m->m_len < off + sizeof(struct icmp6_hdr)) {
334
m = m_pullup(m, off + sizeof(struct icmp6_hdr));
335
if (m == NULL) {
336
IP6STAT_INC(ip6s_exthdrtoolong);
337
return;
338
}
339
}
340
oip6 = mtod(m, struct ip6_hdr *);
341
icp = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
342
343
if (icp->icmp6_type < ICMP6_ECHO_REQUEST ||
344
icp->icmp6_type == ND_REDIRECT) {
345
/*
346
* ICMPv6 error
347
* Special case: for redirect (which is
348
* informational) we must not send icmp6 error.
349
*/
350
ICMP6STAT_INC(icp6s_canterror);
351
goto freeit;
352
} else {
353
/* ICMPv6 informational - send the error */
354
}
355
} else {
356
/* non-ICMPv6 - send the error */
357
}
358
359
/* Finally, do rate limitation check. */
360
if (icmp6_ratelimit(&oip6->ip6_src, type, code))
361
goto freeit;
362
363
/*
364
* OK, ICMP6 can be generated.
365
*/
366
367
if (m->m_pkthdr.len >= ICMPV6_PLD_MAXLEN)
368
m_adj(m, ICMPV6_PLD_MAXLEN - m->m_pkthdr.len);
369
370
preplen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
371
M_PREPEND(m, preplen, M_NOWAIT); /* FIB is also copied over. */
372
if (m == NULL) {
373
nd6log((LOG_DEBUG, "ENOBUFS in icmp6_error %d\n", __LINE__));
374
return;
375
}
376
377
nip6 = mtod(m, struct ip6_hdr *);
378
nip6->ip6_src = oip6->ip6_src;
379
nip6->ip6_dst = oip6->ip6_dst;
380
381
in6_clearscope(&oip6->ip6_src);
382
in6_clearscope(&oip6->ip6_dst);
383
384
icmp6 = (struct icmp6_hdr *)(nip6 + 1);
385
icmp6->icmp6_type = type;
386
icmp6->icmp6_code = code;
387
icmp6->icmp6_pptr = htonl((u_int32_t)param);
388
389
ICMP6STAT_INC2(icp6s_outhist, type);
390
NET_EPOCH_ENTER(et);
391
icmp6_reflect(m, sizeof(struct ip6_hdr)); /* header order: IPv6 - ICMPv6 */
392
NET_EPOCH_EXIT(et);
393
394
return;
395
396
freeit:
397
/*
398
* If we can't tell whether or not we can generate ICMP6, free it.
399
*/
400
m_freem(m);
401
}
402
403
int
404
icmp6_errmap(const struct icmp6_hdr *icmp6)
405
{
406
407
switch (icmp6->icmp6_type) {
408
case ICMP6_DST_UNREACH:
409
switch (icmp6->icmp6_code) {
410
case ICMP6_DST_UNREACH_NOROUTE:
411
case ICMP6_DST_UNREACH_ADDR:
412
return (EHOSTUNREACH);
413
case ICMP6_DST_UNREACH_NOPORT:
414
case ICMP6_DST_UNREACH_ADMIN:
415
return (ECONNREFUSED);
416
case ICMP6_DST_UNREACH_BEYONDSCOPE:
417
return (ENOPROTOOPT);
418
default:
419
return (0); /* Shouldn't happen. */
420
}
421
case ICMP6_PACKET_TOO_BIG:
422
return (EMSGSIZE);
423
case ICMP6_TIME_EXCEEDED:
424
switch (icmp6->icmp6_code) {
425
case ICMP6_TIME_EXCEED_TRANSIT:
426
return (EHOSTUNREACH);
427
case ICMP6_TIME_EXCEED_REASSEMBLY:
428
return (0);
429
default:
430
return (0); /* Shouldn't happen. */
431
}
432
case ICMP6_PARAM_PROB:
433
switch (icmp6->icmp6_code) {
434
case ICMP6_PARAMPROB_NEXTHEADER:
435
return (ECONNREFUSED);
436
case ICMP6_PARAMPROB_HEADER:
437
case ICMP6_PARAMPROB_OPTION:
438
return (ENOPROTOOPT);
439
default:
440
return (0); /* Shouldn't happen. */
441
}
442
default:
443
return (0);
444
}
445
}
446
447
/*
448
* Process a received ICMP6 message.
449
*/
450
int
451
icmp6_input(struct mbuf **mp, int *offp, int proto)
452
{
453
struct mbuf *m, *n;
454
struct ifnet *ifp;
455
struct ip6_hdr *ip6, *nip6;
456
struct icmp6_hdr *icmp6, *nicmp6;
457
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
458
int code, error, icmp6len, ip6len, noff, off, sum;
459
460
NET_EPOCH_ASSERT();
461
462
m = *mp;
463
off = *offp;
464
465
if (m->m_len < off + sizeof(struct icmp6_hdr)) {
466
m = m_pullup(m, off + sizeof(struct icmp6_hdr));
467
if (m == NULL) {
468
IP6STAT_INC(ip6s_exthdrtoolong);
469
*mp = m;
470
return (IPPROTO_DONE);
471
}
472
}
473
474
/*
475
* Locate icmp6 structure in mbuf, and check
476
* that not corrupted and of at least minimum length
477
*/
478
479
icmp6len = m->m_pkthdr.len - off;
480
if (icmp6len < sizeof(struct icmp6_hdr)) {
481
ICMP6STAT_INC(icp6s_tooshort);
482
goto freeit;
483
}
484
485
ip6 = mtod(m, struct ip6_hdr *);
486
ifp = m->m_pkthdr.rcvif;
487
/*
488
* Check multicast group membership.
489
* Note: SSM filters are not applied for ICMPv6 traffic.
490
*/
491
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
492
struct in6_multi *inm;
493
494
inm = in6m_lookup(ifp, &ip6->ip6_dst);
495
if (inm == NULL) {
496
IP6STAT_INC(ip6s_notmember);
497
in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
498
goto freeit;
499
}
500
}
501
502
/* Calculate the checksum. */
503
icmp6 = (struct icmp6_hdr *)((caddr_t)ip6 + off);
504
code = icmp6->icmp6_code;
505
if ((sum = in6_cksum(m, IPPROTO_ICMPV6, off, icmp6len)) != 0) {
506
nd6log((LOG_ERR,
507
"ICMP6 checksum error(%d|%x) %s\n",
508
icmp6->icmp6_type, sum,
509
ip6_sprintf(ip6bufs, &ip6->ip6_src)));
510
ICMP6STAT_INC(icp6s_checksum);
511
goto freeit;
512
}
513
514
ICMP6STAT_INC2(icp6s_inhist, icmp6->icmp6_type);
515
icmp6_ifstat_inc(ifp, ifs6_in_msg);
516
if (icmp6->icmp6_type < ICMP6_INFOMSG_MASK)
517
icmp6_ifstat_inc(ifp, ifs6_in_error);
518
519
ip6len = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen);
520
switch (icmp6->icmp6_type) {
521
case ICMP6_DST_UNREACH:
522
icmp6_ifstat_inc(ifp, ifs6_in_dstunreach);
523
switch (code) {
524
case ICMP6_DST_UNREACH_ADMIN:
525
icmp6_ifstat_inc(ifp, ifs6_in_adminprohib);
526
case ICMP6_DST_UNREACH_NOROUTE:
527
case ICMP6_DST_UNREACH_ADDR:
528
case ICMP6_DST_UNREACH_BEYONDSCOPE:
529
case ICMP6_DST_UNREACH_NOPORT:
530
goto deliver;
531
default:
532
goto badcode;
533
}
534
case ICMP6_PACKET_TOO_BIG:
535
icmp6_ifstat_inc(ifp, ifs6_in_pkttoobig);
536
/*
537
* Validation is made in icmp6_mtudisc_update.
538
* Updating the path MTU will be done after examining
539
* intermediate extension headers.
540
*/
541
goto deliver;
542
case ICMP6_TIME_EXCEEDED:
543
icmp6_ifstat_inc(ifp, ifs6_in_timeexceed);
544
switch (code) {
545
case ICMP6_TIME_EXCEED_TRANSIT:
546
case ICMP6_TIME_EXCEED_REASSEMBLY:
547
goto deliver;
548
default:
549
goto badcode;
550
}
551
case ICMP6_PARAM_PROB:
552
icmp6_ifstat_inc(ifp, ifs6_in_paramprob);
553
switch (code) {
554
case ICMP6_PARAMPROB_NEXTHEADER:
555
case ICMP6_PARAMPROB_HEADER:
556
case ICMP6_PARAMPROB_OPTION:
557
goto deliver;
558
default:
559
goto badcode;
560
}
561
case ICMP6_ECHO_REQUEST:
562
icmp6_ifstat_inc(ifp, ifs6_in_echo);
563
if (code != 0)
564
goto badcode;
565
if (icmp6_ratelimit(&ip6->ip6_src, ICMP6_ECHO_REPLY, 0))
566
break;
567
if ((n = m_copym(m, 0, M_COPYALL, M_NOWAIT)) == NULL) {
568
/* Give up remote */
569
break;
570
}
571
if (!M_WRITABLE(n)
572
|| n->m_len < off + sizeof(struct icmp6_hdr)) {
573
struct mbuf *n0 = n;
574
int n0len;
575
576
CTASSERT(sizeof(*nip6) + sizeof(*nicmp6) <= MHLEN);
577
n = m_gethdr(M_NOWAIT, n0->m_type);
578
if (n == NULL) {
579
/* Give up remote */
580
m_freem(n0);
581
break;
582
}
583
584
m_move_pkthdr(n, n0); /* FIB copied. */
585
n0len = n0->m_pkthdr.len; /* save for use below */
586
/*
587
* Copy IPv6 and ICMPv6 only.
588
*/
589
nip6 = mtod(n, struct ip6_hdr *);
590
bcopy(ip6, nip6, sizeof(struct ip6_hdr));
591
nicmp6 = (struct icmp6_hdr *)(nip6 + 1);
592
bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr));
593
noff = sizeof(struct ip6_hdr);
594
/* new mbuf contains only ipv6+icmpv6 headers */
595
n->m_len = noff + sizeof(struct icmp6_hdr);
596
/*
597
* Adjust mbuf. ip6_plen will be adjusted in
598
* ip6_output().
599
*/
600
m_adj(n0, off + sizeof(struct icmp6_hdr));
601
/* recalculate complete packet size */
602
n->m_pkthdr.len = n0len + (noff - off);
603
n->m_next = n0;
604
} else {
605
if (n->m_len < off + sizeof(*nicmp6)) {
606
n = m_pullup(n, off + sizeof(*nicmp6));
607
if (n == NULL) {
608
IP6STAT_INC(ip6s_exthdrtoolong);
609
break;
610
}
611
}
612
nicmp6 = (struct icmp6_hdr *)(mtod(n, caddr_t) + off);
613
noff = off;
614
}
615
if (n) {
616
nicmp6->icmp6_type = ICMP6_ECHO_REPLY;
617
nicmp6->icmp6_code = 0;
618
ICMP6STAT_INC(icp6s_reflect);
619
ICMP6STAT_INC2(icp6s_outhist, ICMP6_ECHO_REPLY);
620
icmp6_reflect(n, noff);
621
}
622
break;
623
624
case ICMP6_ECHO_REPLY:
625
icmp6_ifstat_inc(ifp, ifs6_in_echoreply);
626
if (code != 0)
627
goto badcode;
628
break;
629
630
case MLD_LISTENER_QUERY:
631
case MLD_LISTENER_REPORT:
632
case MLD_LISTENER_DONE:
633
case MLDV2_LISTENER_REPORT:
634
/*
635
* Drop MLD traffic which is not link-local, has a hop limit
636
* of greater than 1 hop, or which does not have the
637
* IPv6 HBH Router Alert option.
638
* As IPv6 HBH options are stripped in ip6_input() we must
639
* check an mbuf header flag.
640
* XXX Should we also sanity check that these messages
641
* were directed to a link-local multicast prefix?
642
*/
643
if ((ip6->ip6_hlim != 1) || (m->m_flags & M_RTALERT_MLD) == 0)
644
goto freeit;
645
if (mld_input(&m, off, icmp6len) != 0) {
646
*mp = NULL;
647
return (IPPROTO_DONE);
648
}
649
/* m stays. */
650
break;
651
652
case ICMP6_WRUREQUEST: /* ICMP6_FQDN_QUERY */
653
{
654
enum { WRU, FQDN } mode;
655
struct prison *pr;
656
657
if (!V_icmp6_nodeinfo)
658
break;
659
660
if (icmp6len == sizeof(struct icmp6_hdr) + 4)
661
mode = WRU;
662
else if (icmp6len >= sizeof(struct icmp6_nodeinfo))
663
mode = FQDN;
664
else
665
goto badlen;
666
667
pr = NULL;
668
sx_slock(&allprison_lock);
669
TAILQ_FOREACH(pr, &allprison, pr_list)
670
if (pr->pr_vnet == ifp->if_vnet)
671
break;
672
sx_sunlock(&allprison_lock);
673
if (pr == NULL)
674
pr = curthread->td_ucred->cr_prison;
675
if (mode == FQDN) {
676
if (m->m_len < off + sizeof(struct icmp6_nodeinfo)) {
677
m = m_pullup(m, off +
678
sizeof(struct icmp6_nodeinfo));
679
if (m == NULL) {
680
IP6STAT_INC(ip6s_exthdrtoolong);
681
*mp = m;
682
return (IPPROTO_DONE);
683
}
684
}
685
n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
686
if (n)
687
n = ni6_input(n, off, pr);
688
/* XXX meaningless if n == NULL */
689
noff = sizeof(struct ip6_hdr);
690
} else {
691
u_char *p;
692
int maxhlen, hlen;
693
694
/*
695
* XXX: this combination of flags is pointless,
696
* but should we keep this for compatibility?
697
*/
698
if ((V_icmp6_nodeinfo & (ICMP6_NODEINFO_FQDNOK |
699
ICMP6_NODEINFO_TMPADDROK)) !=
700
(ICMP6_NODEINFO_FQDNOK | ICMP6_NODEINFO_TMPADDROK))
701
break;
702
703
if (code != 0)
704
goto badcode;
705
706
CTASSERT(sizeof(*nip6) + sizeof(*nicmp6) + 4 <= MHLEN);
707
n = m_gethdr(M_NOWAIT, m->m_type);
708
if (n == NULL) {
709
/* Give up remote */
710
break;
711
}
712
if (!m_dup_pkthdr(n, m, M_NOWAIT)) {
713
/*
714
* Previous code did a blind M_COPY_PKTHDR
715
* and said "just for rcvif". If true, then
716
* we could tolerate the dup failing (due to
717
* the deep copy of the tag chain). For now
718
* be conservative and just fail.
719
*/
720
m_free(n);
721
n = NULL;
722
break;
723
}
724
/*
725
* Copy IPv6 and ICMPv6 only.
726
*/
727
nip6 = mtod(n, struct ip6_hdr *);
728
bcopy(ip6, nip6, sizeof(struct ip6_hdr));
729
nicmp6 = (struct icmp6_hdr *)(nip6 + 1);
730
bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr));
731
p = (u_char *)(nicmp6 + 1);
732
bzero(p, 4);
733
734
maxhlen = M_TRAILINGSPACE(n) -
735
(sizeof(*nip6) + sizeof(*nicmp6) + 4);
736
mtx_lock(&pr->pr_mtx);
737
hlen = strlen(pr->pr_hostname);
738
if (maxhlen > hlen)
739
maxhlen = hlen;
740
/* meaningless TTL */
741
bcopy(pr->pr_hostname, p + 4, maxhlen);
742
mtx_unlock(&pr->pr_mtx);
743
noff = sizeof(struct ip6_hdr);
744
n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) +
745
sizeof(struct icmp6_hdr) + 4 + maxhlen;
746
nicmp6->icmp6_type = ICMP6_WRUREPLY;
747
nicmp6->icmp6_code = 0;
748
}
749
if (n) {
750
ICMP6STAT_INC(icp6s_reflect);
751
ICMP6STAT_INC2(icp6s_outhist, ICMP6_WRUREPLY);
752
icmp6_reflect(n, noff);
753
}
754
break;
755
}
756
757
case ICMP6_WRUREPLY:
758
if (code != 0)
759
goto badcode;
760
break;
761
762
case ND_ROUTER_SOLICIT:
763
icmp6_ifstat_inc(ifp, ifs6_in_routersolicit);
764
if (code != 0)
765
goto badcode;
766
if (icmp6len < sizeof(struct nd_router_solicit))
767
goto badlen;
768
if (send_sendso_input_hook != NULL) {
769
if (m->m_len < off + icmp6len) {
770
m = m_pullup(m, off + icmp6len);
771
if (m == NULL) {
772
IP6STAT_INC(ip6s_exthdrtoolong);
773
*mp = NULL;
774
return (IPPROTO_DONE);
775
}
776
}
777
error = send_sendso_input_hook(m, ifp, SND_IN, ip6len);
778
if (error == 0) {
779
m = NULL;
780
goto freeit;
781
}
782
}
783
n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
784
nd6_rs_input(m, off, icmp6len);
785
m = n;
786
if (m == NULL)
787
goto freeit;
788
break;
789
790
case ND_ROUTER_ADVERT:
791
icmp6_ifstat_inc(ifp, ifs6_in_routeradvert);
792
if (code != 0)
793
goto badcode;
794
if (icmp6len < sizeof(struct nd_router_advert))
795
goto badlen;
796
if (send_sendso_input_hook != NULL) {
797
error = send_sendso_input_hook(m, ifp, SND_IN, ip6len);
798
if (error == 0) {
799
m = NULL;
800
goto freeit;
801
}
802
}
803
n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
804
nd6_ra_input(m, off, icmp6len);
805
m = n;
806
if (m == NULL)
807
goto freeit;
808
break;
809
810
case ND_NEIGHBOR_SOLICIT:
811
icmp6_ifstat_inc(ifp, ifs6_in_neighborsolicit);
812
if (code != 0)
813
goto badcode;
814
if (icmp6len < sizeof(struct nd_neighbor_solicit))
815
goto badlen;
816
if (send_sendso_input_hook != NULL) {
817
error = send_sendso_input_hook(m, ifp, SND_IN, ip6len);
818
if (error == 0) {
819
m = NULL;
820
goto freeit;
821
}
822
}
823
n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
824
nd6_ns_input(m, off, icmp6len);
825
m = n;
826
if (m == NULL)
827
goto freeit;
828
break;
829
830
case ND_NEIGHBOR_ADVERT:
831
icmp6_ifstat_inc(ifp, ifs6_in_neighboradvert);
832
if (code != 0)
833
goto badcode;
834
if (icmp6len < sizeof(struct nd_neighbor_advert))
835
goto badlen;
836
if (send_sendso_input_hook != NULL) {
837
error = send_sendso_input_hook(m, ifp, SND_IN, ip6len);
838
if (error == 0) {
839
m = NULL;
840
goto freeit;
841
}
842
}
843
n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
844
nd6_na_input(m, off, icmp6len);
845
m = n;
846
if (m == NULL)
847
goto freeit;
848
break;
849
850
case ND_REDIRECT:
851
icmp6_ifstat_inc(ifp, ifs6_in_redirect);
852
if (code != 0)
853
goto badcode;
854
if (icmp6len < sizeof(struct nd_redirect))
855
goto badlen;
856
if (send_sendso_input_hook != NULL) {
857
error = send_sendso_input_hook(m, ifp, SND_IN, ip6len);
858
if (error == 0) {
859
m = NULL;
860
goto freeit;
861
}
862
}
863
n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
864
icmp6_redirect_input(m, off);
865
m = n;
866
if (m == NULL)
867
goto freeit;
868
break;
869
870
case ICMP6_ROUTER_RENUMBERING:
871
if (code != ICMP6_ROUTER_RENUMBERING_COMMAND &&
872
code != ICMP6_ROUTER_RENUMBERING_RESULT)
873
goto badcode;
874
if (icmp6len < sizeof(struct icmp6_router_renum))
875
goto badlen;
876
break;
877
878
default:
879
nd6log((LOG_DEBUG,
880
"icmp6_input: unknown type %d(src=%s, dst=%s, ifid=%d)\n",
881
icmp6->icmp6_type, ip6_sprintf(ip6bufs, &ip6->ip6_src),
882
ip6_sprintf(ip6bufd, &ip6->ip6_dst),
883
ifp ? ifp->if_index : 0));
884
if (icmp6->icmp6_type < ICMP6_ECHO_REQUEST) {
885
/* ICMPv6 error: MUST deliver it by spec... */
886
goto deliver;
887
} else {
888
/* ICMPv6 informational: MUST not deliver */
889
break;
890
}
891
deliver:
892
if (icmp6_notify_error(&m, off, icmp6len) != 0) {
893
/* In this case, m should've been freed. */
894
*mp = NULL;
895
return (IPPROTO_DONE);
896
}
897
break;
898
899
badcode:
900
ICMP6STAT_INC(icp6s_badcode);
901
break;
902
903
badlen:
904
ICMP6STAT_INC(icp6s_badlen);
905
break;
906
}
907
908
/* deliver the packet to appropriate sockets */
909
icmp6_rip6_input(&m, *offp);
910
911
*mp = m;
912
return (IPPROTO_DONE);
913
914
freeit:
915
m_freem(m);
916
*mp = NULL;
917
return (IPPROTO_DONE);
918
}
919
920
static int
921
icmp6_notify_error(struct mbuf **mp, int off, int icmp6len)
922
{
923
struct mbuf *m;
924
struct icmp6_hdr *icmp6;
925
struct ip6_hdr *eip6;
926
u_int32_t notifymtu;
927
struct sockaddr_in6 icmp6src, icmp6dst;
928
929
m = *mp;
930
931
if (icmp6len < sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr)) {
932
ICMP6STAT_INC(icp6s_tooshort);
933
goto freeit;
934
}
935
936
if (m->m_len < off + sizeof(*icmp6) + sizeof(struct ip6_hdr)) {
937
m = m_pullup(m, off + sizeof(*icmp6) + sizeof(struct ip6_hdr));
938
if (m == NULL) {
939
IP6STAT_INC(ip6s_exthdrtoolong);
940
*mp = m;
941
return (-1);
942
}
943
}
944
icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
945
eip6 = (struct ip6_hdr *)(icmp6 + 1);
946
bzero(&icmp6dst, sizeof(icmp6dst));
947
948
/* Detect the upper level protocol */
949
{
950
u_int8_t nxt = eip6->ip6_nxt;
951
int eoff = off + sizeof(struct icmp6_hdr) +
952
sizeof(struct ip6_hdr);
953
struct ip6ctlparam ip6cp;
954
int icmp6type = icmp6->icmp6_type;
955
struct ip6_frag *fh;
956
struct ip6_rthdr *rth;
957
struct ip6_rthdr0 *rth0;
958
int rthlen;
959
960
while (1) { /* XXX: should avoid infinite loop explicitly? */
961
struct ip6_ext *eh;
962
963
switch (nxt) {
964
case IPPROTO_HOPOPTS:
965
case IPPROTO_DSTOPTS:
966
case IPPROTO_AH:
967
if (m->m_len < eoff + sizeof(struct ip6_ext)) {
968
m = m_pullup(m, eoff +
969
sizeof(struct ip6_ext));
970
if (m == NULL) {
971
IP6STAT_INC(ip6s_exthdrtoolong);
972
*mp = m;
973
return (-1);
974
}
975
}
976
eh = (struct ip6_ext *)
977
(mtod(m, caddr_t) + eoff);
978
if (nxt == IPPROTO_AH)
979
eoff += (eh->ip6e_len + 2) << 2;
980
else
981
eoff += (eh->ip6e_len + 1) << 3;
982
nxt = eh->ip6e_nxt;
983
break;
984
case IPPROTO_ROUTING:
985
/*
986
* When the erroneous packet contains a
987
* routing header, we should examine the
988
* header to determine the final destination.
989
* Otherwise, we can't properly update
990
* information that depends on the final
991
* destination (e.g. path MTU).
992
*/
993
if (m->m_len < eoff + sizeof(*rth)) {
994
m = m_pullup(m, eoff + sizeof(*rth));
995
if (m == NULL) {
996
IP6STAT_INC(ip6s_exthdrtoolong);
997
*mp = m;
998
return (-1);
999
}
1000
}
1001
rth = (struct ip6_rthdr *)
1002
(mtod(m, caddr_t) + eoff);
1003
rthlen = (rth->ip6r_len + 1) << 3;
1004
/*
1005
* XXX: currently there is no
1006
* officially defined type other
1007
* than type-0.
1008
* Note that if the segment left field
1009
* is 0, all intermediate hops must
1010
* have been passed.
1011
*/
1012
if (rth->ip6r_segleft &&
1013
rth->ip6r_type == IPV6_RTHDR_TYPE_0) {
1014
int hops;
1015
1016
if (m->m_len < eoff + rthlen) {
1017
m = m_pullup(m, eoff + rthlen);
1018
if (m == NULL) {
1019
IP6STAT_INC(
1020
ip6s_exthdrtoolong);
1021
*mp = m;
1022
return (-1);
1023
}
1024
}
1025
rth0 = (struct ip6_rthdr0 *)
1026
(mtod(m, caddr_t) + eoff);
1027
1028
/* just ignore a bogus header */
1029
if ((rth0->ip6r0_len % 2) == 0 &&
1030
(hops = rth0->ip6r0_len/2))
1031
icmp6dst.sin6_addr = *((struct in6_addr *)(rth0 + 1) + (hops - 1));
1032
}
1033
eoff += rthlen;
1034
nxt = rth->ip6r_nxt;
1035
break;
1036
case IPPROTO_FRAGMENT:
1037
if (m->m_len < eoff + sizeof(struct ip6_frag)) {
1038
m = m_pullup(m, eoff +
1039
sizeof(struct ip6_frag));
1040
if (m == NULL) {
1041
IP6STAT_INC(ip6s_exthdrtoolong);
1042
*mp = m;
1043
return (-1);
1044
}
1045
}
1046
fh = (struct ip6_frag *)(mtod(m, caddr_t) +
1047
eoff);
1048
/*
1049
* Data after a fragment header is meaningless
1050
* unless it is the first fragment, but
1051
* we'll go to the notify label for path MTU
1052
* discovery.
1053
*/
1054
if (fh->ip6f_offlg & IP6F_OFF_MASK)
1055
goto notify;
1056
1057
eoff += sizeof(struct ip6_frag);
1058
nxt = fh->ip6f_nxt;
1059
break;
1060
default:
1061
/*
1062
* This case includes ESP and the No Next
1063
* Header. In such cases going to the notify
1064
* label does not have any meaning
1065
* (i.e. ctlfunc will be NULL), but we go
1066
* anyway since we might have to update
1067
* path MTU information.
1068
*/
1069
goto notify;
1070
}
1071
}
1072
notify:
1073
icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
1074
1075
/*
1076
* retrieve parameters from the inner IPv6 header, and convert
1077
* them into sockaddr structures.
1078
* XXX: there is no guarantee that the source or destination
1079
* addresses of the inner packet are in the same scope as
1080
* the addresses of the icmp packet. But there is no other
1081
* way to determine the zone.
1082
*/
1083
eip6 = (struct ip6_hdr *)(icmp6 + 1);
1084
1085
/*
1086
* Protocol layers can't do anything useful with unspecified
1087
* addresses.
1088
*/
1089
if (IN6_IS_ADDR_UNSPECIFIED(&eip6->ip6_src) ||
1090
IN6_IS_ADDR_UNSPECIFIED(&eip6->ip6_dst))
1091
goto freeit;
1092
1093
icmp6dst.sin6_len = sizeof(struct sockaddr_in6);
1094
icmp6dst.sin6_family = AF_INET6;
1095
if (IN6_IS_ADDR_UNSPECIFIED(&icmp6dst.sin6_addr))
1096
icmp6dst.sin6_addr = eip6->ip6_dst;
1097
if (in6_setscope(&icmp6dst.sin6_addr, m->m_pkthdr.rcvif, NULL))
1098
goto freeit;
1099
bzero(&icmp6src, sizeof(icmp6src));
1100
icmp6src.sin6_len = sizeof(struct sockaddr_in6);
1101
icmp6src.sin6_family = AF_INET6;
1102
icmp6src.sin6_addr = eip6->ip6_src;
1103
if (in6_setscope(&icmp6src.sin6_addr, m->m_pkthdr.rcvif, NULL))
1104
goto freeit;
1105
icmp6src.sin6_flowinfo =
1106
(eip6->ip6_flow & IPV6_FLOWLABEL_MASK);
1107
1108
ip6cp.ip6c_m = m;
1109
ip6cp.ip6c_icmp6 = icmp6;
1110
ip6cp.ip6c_ip6 = (struct ip6_hdr *)(icmp6 + 1);
1111
ip6cp.ip6c_off = eoff;
1112
ip6cp.ip6c_finaldst = &icmp6dst;
1113
ip6cp.ip6c_src = &icmp6src;
1114
ip6cp.ip6c_nxt = nxt;
1115
1116
if (icmp6type == ICMP6_PACKET_TOO_BIG) {
1117
notifymtu = ntohl(icmp6->icmp6_mtu);
1118
ip6cp.ip6c_cmdarg = (void *)&notifymtu;
1119
icmp6_mtudisc_update(&ip6cp);
1120
}
1121
1122
if (ip6_ctlprotox[nxt] != NULL)
1123
ip6_ctlprotox[nxt](&ip6cp);
1124
}
1125
*mp = m;
1126
return (0);
1127
1128
freeit:
1129
m_freem(m);
1130
*mp = NULL;
1131
return (-1);
1132
}
1133
1134
static void
1135
icmp6_mtudisc_update(struct ip6ctlparam *ip6cp)
1136
{
1137
struct in6_addr *dst = &ip6cp->ip6c_finaldst->sin6_addr;
1138
struct icmp6_hdr *icmp6 = ip6cp->ip6c_icmp6;
1139
struct mbuf *m = ip6cp->ip6c_m;
1140
u_int mtu = ntohl(icmp6->icmp6_mtu);
1141
struct in_conninfo inc;
1142
uint32_t max_mtu;
1143
1144
if (mtu < IPV6_MMTU)
1145
return;
1146
1147
bzero(&inc, sizeof(inc));
1148
inc.inc_fibnum = M_GETFIB(m);
1149
inc.inc_flags |= INC_ISIPV6;
1150
inc.inc6_faddr = *dst;
1151
if (in6_setscope(&inc.inc6_faddr, m->m_pkthdr.rcvif, NULL))
1152
return;
1153
1154
max_mtu = tcp_hc_getmtu(&inc);
1155
if (max_mtu == 0)
1156
max_mtu = tcp_maxmtu6(&inc, NULL);
1157
1158
if (mtu < max_mtu) {
1159
tcp_hc_updatemtu(&inc, mtu);
1160
ICMP6STAT_INC(icp6s_pmtuchg);
1161
}
1162
}
1163
1164
/*
1165
* Process a Node Information Query packet, based on
1166
* draft-ietf-ipngwg-icmp-name-lookups-07.
1167
*
1168
* Spec incompatibilities:
1169
* - IPv6 Subject address handling
1170
* - IPv4 Subject address handling support missing
1171
* - Proxy reply (answer even if it's not for me)
1172
* - joins NI group address at in6_ifattach() time only, does not cope
1173
* with hostname changes by sethostname(3)
1174
*/
1175
static struct mbuf *
1176
ni6_input(struct mbuf *m, int off, struct prison *pr)
1177
{
1178
struct icmp6_nodeinfo *ni6, *nni6;
1179
struct mbuf *n = NULL;
1180
u_int16_t qtype;
1181
int subjlen;
1182
int replylen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo);
1183
struct ni_reply_fqdn *fqdn;
1184
int addrs; /* for NI_QTYPE_NODEADDR */
1185
struct ifnet *ifp = NULL; /* for NI_QTYPE_NODEADDR */
1186
struct in6_addr in6_subj; /* subject address */
1187
struct ip6_hdr *ip6;
1188
int oldfqdn = 0; /* if 1, return pascal string (03 draft) */
1189
char *subj = NULL;
1190
struct in6_ifaddr *ia6 = NULL;
1191
1192
ip6 = mtod(m, struct ip6_hdr *);
1193
ni6 = (struct icmp6_nodeinfo *)(mtod(m, caddr_t) + off);
1194
1195
/*
1196
* Validate IPv6 source address.
1197
* The default configuration MUST be to refuse answering queries from
1198
* global-scope addresses according to RFC4602.
1199
* Notes:
1200
* - it's not very clear what "refuse" means; this implementation
1201
* simply drops it.
1202
* - it's not very easy to identify global-scope (unicast) addresses
1203
* since there are many prefixes for them. It should be safer
1204
* and in practice sufficient to check "all" but loopback and
1205
* link-local (note that site-local unicast was deprecated and
1206
* ULA is defined as global scope-wise)
1207
*/
1208
if ((V_icmp6_nodeinfo & ICMP6_NODEINFO_GLOBALOK) == 0 &&
1209
!IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) &&
1210
!IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src))
1211
goto bad;
1212
1213
/*
1214
* Validate IPv6 destination address.
1215
*
1216
* The Responder must discard the Query without further processing
1217
* unless it is one of the Responder's unicast or anycast addresses, or
1218
* a link-local scope multicast address which the Responder has joined.
1219
* [RFC4602, Section 5.]
1220
*/
1221
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
1222
if (!IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst))
1223
goto bad;
1224
/* else it's a link-local multicast, fine */
1225
} else { /* unicast or anycast */
1226
ia6 = in6ifa_ifwithaddr(&ip6->ip6_dst, 0 /* XXX */, false);
1227
if (ia6 == NULL)
1228
goto bad; /* XXX impossible */
1229
1230
if ((ia6->ia6_flags & IN6_IFF_TEMPORARY) &&
1231
!(V_icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK)) {
1232
nd6log((LOG_DEBUG, "ni6_input: ignore node info to "
1233
"a temporary address in %s:%d",
1234
__FILE__, __LINE__));
1235
goto bad;
1236
}
1237
}
1238
1239
/* validate query Subject field. */
1240
qtype = ntohs(ni6->ni_qtype);
1241
subjlen = m->m_pkthdr.len - off - sizeof(struct icmp6_nodeinfo);
1242
switch (qtype) {
1243
case NI_QTYPE_NOOP:
1244
case NI_QTYPE_SUPTYPES:
1245
/* 07 draft */
1246
if (ni6->ni_code == ICMP6_NI_SUBJ_FQDN && subjlen == 0)
1247
break;
1248
/* FALLTHROUGH */
1249
case NI_QTYPE_FQDN:
1250
case NI_QTYPE_NODEADDR:
1251
case NI_QTYPE_IPV4ADDR:
1252
switch (ni6->ni_code) {
1253
case ICMP6_NI_SUBJ_IPV6:
1254
#if ICMP6_NI_SUBJ_IPV6 != 0
1255
case 0:
1256
#endif
1257
/*
1258
* backward compatibility - try to accept 03 draft
1259
* format, where no Subject is present.
1260
*/
1261
if (qtype == NI_QTYPE_FQDN && ni6->ni_code == 0 &&
1262
subjlen == 0) {
1263
oldfqdn++;
1264
break;
1265
}
1266
#if ICMP6_NI_SUBJ_IPV6 != 0
1267
if (ni6->ni_code != ICMP6_NI_SUBJ_IPV6)
1268
goto bad;
1269
#endif
1270
1271
if (subjlen != sizeof(struct in6_addr))
1272
goto bad;
1273
1274
/*
1275
* Validate Subject address.
1276
*
1277
* Not sure what exactly "address belongs to the node"
1278
* means in the spec, is it just unicast, or what?
1279
*
1280
* At this moment we consider Subject address as
1281
* "belong to the node" if the Subject address equals
1282
* to the IPv6 destination address; validation for
1283
* IPv6 destination address should have done enough
1284
* check for us.
1285
*
1286
* We do not do proxy at this moment.
1287
*/
1288
m_copydata(m, off + sizeof(struct icmp6_nodeinfo),
1289
subjlen, (caddr_t)&in6_subj);
1290
if (in6_setscope(&in6_subj, m->m_pkthdr.rcvif, NULL))
1291
goto bad;
1292
1293
subj = (char *)&in6_subj;
1294
if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &in6_subj))
1295
break;
1296
1297
/*
1298
* XXX if we are to allow other cases, we should really
1299
* be careful about scope here.
1300
* basically, we should disallow queries toward IPv6
1301
* destination X with subject Y,
1302
* if scope(X) > scope(Y).
1303
* if we allow scope(X) > scope(Y), it will result in
1304
* information leakage across scope boundary.
1305
*/
1306
goto bad;
1307
1308
case ICMP6_NI_SUBJ_FQDN:
1309
/*
1310
* Validate Subject name with gethostname(3).
1311
*
1312
* The behavior may need some debate, since:
1313
* - we are not sure if the node has FQDN as
1314
* hostname (returned by gethostname(3)).
1315
* - the code does wildcard match for truncated names.
1316
* however, we are not sure if we want to perform
1317
* wildcard match, if gethostname(3) side has
1318
* truncated hostname.
1319
*/
1320
mtx_lock(&pr->pr_mtx);
1321
n = ni6_nametodns(pr->pr_hostname,
1322
strlen(pr->pr_hostname), 0);
1323
mtx_unlock(&pr->pr_mtx);
1324
if (!n || n->m_next || n->m_len == 0)
1325
goto bad;
1326
if (m->m_len < off + sizeof(struct icmp6_nodeinfo) +
1327
subjlen) {
1328
m = m_pullup(m, off +
1329
sizeof(struct icmp6_nodeinfo) + subjlen);
1330
if (m == NULL) {
1331
IP6STAT_INC(ip6s_exthdrtoolong);
1332
goto bad;
1333
}
1334
}
1335
/* ip6 possibly invalid but not used after. */
1336
ni6 = (struct icmp6_nodeinfo *)(mtod(m, caddr_t) + off);
1337
subj = (char *)(mtod(m, caddr_t) + off +
1338
sizeof(struct icmp6_nodeinfo));
1339
if (!ni6_dnsmatch(subj, subjlen, mtod(n, const char *),
1340
n->m_len)) {
1341
goto bad;
1342
}
1343
m_freem(n);
1344
n = NULL;
1345
break;
1346
1347
case ICMP6_NI_SUBJ_IPV4: /* XXX: to be implemented? */
1348
default:
1349
goto bad;
1350
}
1351
break;
1352
}
1353
1354
/* refuse based on configuration. XXX ICMP6_NI_REFUSED? */
1355
switch (qtype) {
1356
case NI_QTYPE_FQDN:
1357
if ((V_icmp6_nodeinfo & ICMP6_NODEINFO_FQDNOK) == 0)
1358
goto bad;
1359
break;
1360
case NI_QTYPE_NODEADDR:
1361
case NI_QTYPE_IPV4ADDR:
1362
if ((V_icmp6_nodeinfo & ICMP6_NODEINFO_NODEADDROK) == 0)
1363
goto bad;
1364
break;
1365
}
1366
1367
/* guess reply length */
1368
switch (qtype) {
1369
case NI_QTYPE_NOOP:
1370
break; /* no reply data */
1371
case NI_QTYPE_SUPTYPES:
1372
replylen += sizeof(u_int32_t);
1373
break;
1374
case NI_QTYPE_FQDN:
1375
/* XXX will append an mbuf */
1376
replylen += offsetof(struct ni_reply_fqdn, ni_fqdn_namelen);
1377
break;
1378
case NI_QTYPE_NODEADDR:
1379
addrs = ni6_addrs(ni6, m, &ifp, (struct in6_addr *)subj);
1380
if ((replylen += addrs * (sizeof(struct in6_addr) +
1381
sizeof(u_int32_t))) > MCLBYTES)
1382
replylen = MCLBYTES; /* XXX: will truncate pkt later */
1383
break;
1384
case NI_QTYPE_IPV4ADDR:
1385
/* unsupported - should respond with unknown Qtype? */
1386
break;
1387
default:
1388
/*
1389
* XXX: We must return a reply with the ICMP6 code
1390
* `unknown Qtype' in this case. However we regard the case
1391
* as an FQDN query for backward compatibility.
1392
* Older versions set a random value to this field,
1393
* so it rarely varies in the defined qtypes.
1394
* But the mechanism is not reliable...
1395
* maybe we should obsolete older versions.
1396
*/
1397
qtype = NI_QTYPE_FQDN;
1398
/* XXX will append an mbuf */
1399
replylen += offsetof(struct ni_reply_fqdn, ni_fqdn_namelen);
1400
oldfqdn++;
1401
break;
1402
}
1403
1404
/* Allocate an mbuf to reply. */
1405
if (replylen > MCLBYTES) {
1406
/*
1407
* XXX: should we try to allocate more? But MCLBYTES
1408
* is probably much larger than IPV6_MMTU...
1409
*/
1410
goto bad;
1411
}
1412
if (replylen > MHLEN)
1413
n = m_getcl(M_NOWAIT, m->m_type, M_PKTHDR);
1414
else
1415
n = m_gethdr(M_NOWAIT, m->m_type);
1416
if (n == NULL) {
1417
m_freem(m);
1418
return (NULL);
1419
}
1420
m_move_pkthdr(n, m); /* just for recvif and FIB */
1421
n->m_pkthdr.len = n->m_len = replylen;
1422
1423
/* copy mbuf header and IPv6 + Node Information base headers */
1424
bcopy(mtod(m, caddr_t), mtod(n, caddr_t), sizeof(struct ip6_hdr));
1425
nni6 = (struct icmp6_nodeinfo *)(mtod(n, struct ip6_hdr *) + 1);
1426
bcopy((caddr_t)ni6, (caddr_t)nni6, sizeof(struct icmp6_nodeinfo));
1427
1428
/* qtype dependent procedure */
1429
switch (qtype) {
1430
case NI_QTYPE_NOOP:
1431
nni6->ni_code = ICMP6_NI_SUCCESS;
1432
nni6->ni_flags = 0;
1433
break;
1434
case NI_QTYPE_SUPTYPES:
1435
{
1436
u_int32_t v;
1437
nni6->ni_code = ICMP6_NI_SUCCESS;
1438
nni6->ni_flags = htons(0x0000); /* raw bitmap */
1439
/* supports NOOP, SUPTYPES, FQDN, and NODEADDR */
1440
v = (u_int32_t)htonl(0x0000000f);
1441
bcopy(&v, nni6 + 1, sizeof(u_int32_t));
1442
break;
1443
}
1444
case NI_QTYPE_FQDN:
1445
nni6->ni_code = ICMP6_NI_SUCCESS;
1446
fqdn = (struct ni_reply_fqdn *)(mtod(n, caddr_t) +
1447
sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo));
1448
nni6->ni_flags = 0; /* XXX: meaningless TTL */
1449
fqdn->ni_fqdn_ttl = 0; /* ditto. */
1450
/*
1451
* XXX do we really have FQDN in hostname?
1452
*/
1453
mtx_lock(&pr->pr_mtx);
1454
n->m_next = ni6_nametodns(pr->pr_hostname,
1455
strlen(pr->pr_hostname), oldfqdn);
1456
mtx_unlock(&pr->pr_mtx);
1457
if (n->m_next == NULL)
1458
goto bad;
1459
/* XXX we assume that n->m_next is not a chain */
1460
if (n->m_next->m_next != NULL)
1461
goto bad;
1462
n->m_pkthdr.len += n->m_next->m_len;
1463
break;
1464
case NI_QTYPE_NODEADDR:
1465
{
1466
int lenlim, copied;
1467
1468
nni6->ni_code = ICMP6_NI_SUCCESS;
1469
n->m_pkthdr.len = n->m_len =
1470
sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo);
1471
lenlim = M_TRAILINGSPACE(n);
1472
copied = ni6_store_addrs(ni6, nni6, ifp, lenlim);
1473
/* XXX: reset mbuf length */
1474
n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) +
1475
sizeof(struct icmp6_nodeinfo) + copied;
1476
break;
1477
}
1478
default:
1479
break; /* XXX impossible! */
1480
}
1481
1482
nni6->ni_type = ICMP6_NI_REPLY;
1483
m_freem(m);
1484
return (n);
1485
1486
bad:
1487
m_freem(m);
1488
if (n)
1489
m_freem(n);
1490
return (NULL);
1491
}
1492
1493
/*
1494
* make a mbuf with DNS-encoded string. no compression support.
1495
*
1496
* XXX names with less than 2 dots (like "foo" or "foo.section") will be
1497
* treated as truncated name (two \0 at the end). this is a wild guess.
1498
*
1499
* old - return pascal string if non-zero
1500
*/
1501
static struct mbuf *
1502
ni6_nametodns(const char *name, int namelen, int old)
1503
{
1504
struct mbuf *m;
1505
char *cp, *ep;
1506
const char *p, *q;
1507
int i, len, nterm;
1508
1509
if (old)
1510
len = namelen + 1;
1511
else
1512
len = MCLBYTES;
1513
1514
/* Because MAXHOSTNAMELEN is usually 256, we use cluster mbuf. */
1515
if (len > MLEN)
1516
m = m_getcl(M_NOWAIT, MT_DATA, 0);
1517
else
1518
m = m_get(M_NOWAIT, MT_DATA);
1519
if (m == NULL)
1520
goto fail;
1521
1522
if (old) {
1523
m->m_len = len;
1524
*mtod(m, char *) = namelen;
1525
bcopy(name, mtod(m, char *) + 1, namelen);
1526
return m;
1527
} else {
1528
m->m_len = 0;
1529
cp = mtod(m, char *);
1530
ep = mtod(m, char *) + M_TRAILINGSPACE(m);
1531
1532
/* if not certain about my name, return empty buffer */
1533
if (namelen == 0)
1534
return m;
1535
1536
/*
1537
* guess if it looks like shortened hostname, or FQDN.
1538
* shortened hostname needs two trailing "\0".
1539
*/
1540
i = 0;
1541
for (p = name; p < name + namelen; p++) {
1542
if (*p && *p == '.')
1543
i++;
1544
}
1545
if (i < 2)
1546
nterm = 2;
1547
else
1548
nterm = 1;
1549
1550
p = name;
1551
while (cp < ep && p < name + namelen) {
1552
i = 0;
1553
for (q = p; q < name + namelen && *q && *q != '.'; q++)
1554
i++;
1555
/* result does not fit into mbuf */
1556
if (cp + i + 1 >= ep)
1557
goto fail;
1558
/*
1559
* DNS label length restriction, RFC1035 page 8.
1560
* "i == 0" case is included here to avoid returning
1561
* 0-length label on "foo..bar".
1562
*/
1563
if (i <= 0 || i >= 64)
1564
goto fail;
1565
*cp++ = i;
1566
bcopy(p, cp, i);
1567
cp += i;
1568
p = q;
1569
if (p < name + namelen && *p == '.')
1570
p++;
1571
}
1572
/* termination */
1573
if (cp + nterm >= ep)
1574
goto fail;
1575
while (nterm-- > 0)
1576
*cp++ = '\0';
1577
m->m_len = cp - mtod(m, char *);
1578
return m;
1579
}
1580
1581
panic("should not reach here");
1582
/* NOTREACHED */
1583
1584
fail:
1585
if (m)
1586
m_freem(m);
1587
return NULL;
1588
}
1589
1590
/*
1591
* check if two DNS-encoded string matches. takes care of truncated
1592
* form (with \0\0 at the end). no compression support.
1593
* XXX upper/lowercase match (see RFC2065)
1594
*/
1595
static int
1596
ni6_dnsmatch(const char *a, int alen, const char *b, int blen)
1597
{
1598
const char *a0, *b0;
1599
int l;
1600
1601
/* simplest case - need validation? */
1602
if (alen == blen && bcmp(a, b, alen) == 0)
1603
return 1;
1604
1605
a0 = a;
1606
b0 = b;
1607
1608
/* termination is mandatory */
1609
if (alen < 2 || blen < 2)
1610
return 0;
1611
if (a0[alen - 1] != '\0' || b0[blen - 1] != '\0')
1612
return 0;
1613
alen--;
1614
blen--;
1615
1616
while (a - a0 < alen && b - b0 < blen) {
1617
if (a - a0 + 1 > alen || b - b0 + 1 > blen)
1618
return 0;
1619
1620
if ((signed char)a[0] < 0 || (signed char)b[0] < 0)
1621
return 0;
1622
/* we don't support compression yet */
1623
if (a[0] >= 64 || b[0] >= 64)
1624
return 0;
1625
1626
/* truncated case */
1627
if (a[0] == 0 && a - a0 == alen - 1)
1628
return 1;
1629
if (b[0] == 0 && b - b0 == blen - 1)
1630
return 1;
1631
if (a[0] == 0 || b[0] == 0)
1632
return 0;
1633
1634
if (a[0] != b[0])
1635
return 0;
1636
l = a[0];
1637
if (a - a0 + 1 + l > alen || b - b0 + 1 + l > blen)
1638
return 0;
1639
if (bcmp(a + 1, b + 1, l) != 0)
1640
return 0;
1641
1642
a += 1 + l;
1643
b += 1 + l;
1644
}
1645
1646
if (a - a0 == alen && b - b0 == blen)
1647
return 1;
1648
else
1649
return 0;
1650
}
1651
1652
/*
1653
* calculate the number of addresses to be returned in the node info reply.
1654
*/
1655
static int
1656
ni6_addrs(struct icmp6_nodeinfo *ni6, struct mbuf *m, struct ifnet **ifpp,
1657
struct in6_addr *subj)
1658
{
1659
struct ifnet *ifp;
1660
struct in6_ifaddr *ifa6;
1661
struct ifaddr *ifa;
1662
int addrs = 0, addrsofif, iffound = 0;
1663
int niflags = ni6->ni_flags;
1664
1665
NET_EPOCH_ASSERT();
1666
1667
if ((niflags & NI_NODEADDR_FLAG_ALL) == 0) {
1668
switch (ni6->ni_code) {
1669
case ICMP6_NI_SUBJ_IPV6:
1670
if (subj == NULL) /* must be impossible... */
1671
return (0);
1672
break;
1673
default:
1674
/*
1675
* XXX: we only support IPv6 subject address for
1676
* this Qtype.
1677
*/
1678
return (0);
1679
}
1680
}
1681
1682
CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
1683
addrsofif = 0;
1684
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1685
if (ifa->ifa_addr->sa_family != AF_INET6)
1686
continue;
1687
ifa6 = (struct in6_ifaddr *)ifa;
1688
1689
if ((niflags & NI_NODEADDR_FLAG_ALL) == 0 &&
1690
IN6_ARE_ADDR_EQUAL(subj, &ifa6->ia_addr.sin6_addr))
1691
iffound = 1;
1692
1693
/*
1694
* IPv4-mapped addresses can only be returned by a
1695
* Node Information proxy, since they represent
1696
* addresses of IPv4-only nodes, which perforce do
1697
* not implement this protocol.
1698
* [icmp-name-lookups-07, Section 5.4]
1699
* So we don't support NI_NODEADDR_FLAG_COMPAT in
1700
* this function at this moment.
1701
*/
1702
1703
/* What do we have to do about ::1? */
1704
switch (in6_addrscope(&ifa6->ia_addr.sin6_addr)) {
1705
case IPV6_ADDR_SCOPE_LINKLOCAL:
1706
if ((niflags & NI_NODEADDR_FLAG_LINKLOCAL) == 0)
1707
continue;
1708
break;
1709
case IPV6_ADDR_SCOPE_SITELOCAL:
1710
if ((niflags & NI_NODEADDR_FLAG_SITELOCAL) == 0)
1711
continue;
1712
break;
1713
case IPV6_ADDR_SCOPE_GLOBAL:
1714
if ((niflags & NI_NODEADDR_FLAG_GLOBAL) == 0)
1715
continue;
1716
break;
1717
default:
1718
continue;
1719
}
1720
1721
/*
1722
* check if anycast is okay.
1723
* XXX: just experimental. not in the spec.
1724
*/
1725
if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0 &&
1726
(niflags & NI_NODEADDR_FLAG_ANYCAST) == 0)
1727
continue; /* we need only unicast addresses */
1728
if ((ifa6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
1729
(V_icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK) == 0) {
1730
continue;
1731
}
1732
addrsofif++; /* count the address */
1733
}
1734
if (iffound) {
1735
*ifpp = ifp;
1736
return (addrsofif);
1737
}
1738
1739
addrs += addrsofif;
1740
}
1741
1742
return (addrs);
1743
}
1744
1745
static int
1746
ni6_store_addrs(struct icmp6_nodeinfo *ni6, struct icmp6_nodeinfo *nni6,
1747
struct ifnet *ifp0, int resid)
1748
{
1749
struct ifnet *ifp;
1750
struct in6_ifaddr *ifa6;
1751
struct ifaddr *ifa;
1752
struct ifnet *ifp_dep = NULL;
1753
int copied = 0, allow_deprecated = 0;
1754
u_char *cp = (u_char *)(nni6 + 1);
1755
int niflags = ni6->ni_flags;
1756
u_int32_t ltime;
1757
1758
NET_EPOCH_ASSERT();
1759
1760
if (ifp0 == NULL && !(niflags & NI_NODEADDR_FLAG_ALL))
1761
return (0); /* needless to copy */
1762
1763
ifp = ifp0 ? ifp0 : CK_STAILQ_FIRST(&V_ifnet);
1764
again:
1765
1766
for (; ifp; ifp = CK_STAILQ_NEXT(ifp, if_link)) {
1767
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1768
if (ifa->ifa_addr->sa_family != AF_INET6)
1769
continue;
1770
ifa6 = (struct in6_ifaddr *)ifa;
1771
1772
if ((ifa6->ia6_flags & IN6_IFF_DEPRECATED) != 0 &&
1773
allow_deprecated == 0) {
1774
/*
1775
* prefererred address should be put before
1776
* deprecated addresses.
1777
*/
1778
1779
/* record the interface for later search */
1780
if (ifp_dep == NULL)
1781
ifp_dep = ifp;
1782
1783
continue;
1784
} else if ((ifa6->ia6_flags & IN6_IFF_DEPRECATED) == 0 &&
1785
allow_deprecated != 0)
1786
continue; /* we now collect deprecated addrs */
1787
1788
/* What do we have to do about ::1? */
1789
switch (in6_addrscope(&ifa6->ia_addr.sin6_addr)) {
1790
case IPV6_ADDR_SCOPE_LINKLOCAL:
1791
if ((niflags & NI_NODEADDR_FLAG_LINKLOCAL) == 0)
1792
continue;
1793
break;
1794
case IPV6_ADDR_SCOPE_SITELOCAL:
1795
if ((niflags & NI_NODEADDR_FLAG_SITELOCAL) == 0)
1796
continue;
1797
break;
1798
case IPV6_ADDR_SCOPE_GLOBAL:
1799
if ((niflags & NI_NODEADDR_FLAG_GLOBAL) == 0)
1800
continue;
1801
break;
1802
default:
1803
continue;
1804
}
1805
1806
/*
1807
* check if anycast is okay.
1808
* XXX: just experimental. not in the spec.
1809
*/
1810
if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0 &&
1811
(niflags & NI_NODEADDR_FLAG_ANYCAST) == 0)
1812
continue;
1813
if ((ifa6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
1814
(V_icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK) == 0) {
1815
continue;
1816
}
1817
1818
/* now we can copy the address */
1819
if (resid < sizeof(struct in6_addr) +
1820
sizeof(u_int32_t)) {
1821
/*
1822
* We give up much more copy.
1823
* Set the truncate flag and return.
1824
*/
1825
nni6->ni_flags |= NI_NODEADDR_FLAG_TRUNCATE;
1826
return (copied);
1827
}
1828
1829
/*
1830
* Set the TTL of the address.
1831
* The TTL value should be one of the following
1832
* according to the specification:
1833
*
1834
* 1. The remaining lifetime of a DHCP lease on the
1835
* address, or
1836
* 2. The remaining Valid Lifetime of a prefix from
1837
* which the address was derived through Stateless
1838
* Autoconfiguration.
1839
*
1840
* Note that we currently do not support stateful
1841
* address configuration by DHCPv6, so the former
1842
* case can't happen.
1843
*/
1844
if (ifa6->ia6_lifetime.ia6t_expire == 0)
1845
ltime = ND6_INFINITE_LIFETIME;
1846
else {
1847
if (ifa6->ia6_lifetime.ia6t_expire >
1848
time_uptime)
1849
ltime = htonl(ifa6->ia6_lifetime.ia6t_expire - time_uptime);
1850
else
1851
ltime = 0;
1852
}
1853
1854
bcopy(&ltime, cp, sizeof(u_int32_t));
1855
cp += sizeof(u_int32_t);
1856
1857
/* copy the address itself */
1858
bcopy(&ifa6->ia_addr.sin6_addr, cp,
1859
sizeof(struct in6_addr));
1860
in6_clearscope((struct in6_addr *)cp); /* XXX */
1861
cp += sizeof(struct in6_addr);
1862
1863
resid -= (sizeof(struct in6_addr) + sizeof(u_int32_t));
1864
copied += (sizeof(struct in6_addr) + sizeof(u_int32_t));
1865
}
1866
if (ifp0) /* we need search only on the specified IF */
1867
break;
1868
}
1869
1870
if (allow_deprecated == 0 && ifp_dep != NULL) {
1871
ifp = ifp_dep;
1872
allow_deprecated = 1;
1873
1874
goto again;
1875
}
1876
1877
return (copied);
1878
}
1879
1880
static bool
1881
icmp6_rip6_match(const struct inpcb *inp, void *v)
1882
{
1883
struct ip6_hdr *ip6 = v;
1884
1885
if ((inp->inp_vflag & INP_IPV6) == 0)
1886
return (false);
1887
if (inp->inp_ip_p != IPPROTO_ICMPV6)
1888
return (false);
1889
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) &&
1890
!IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, &ip6->ip6_dst))
1891
return (false);
1892
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) &&
1893
!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, &ip6->ip6_src))
1894
return (false);
1895
return (true);
1896
}
1897
1898
/*
1899
* XXX almost dup'ed code with rip6_input.
1900
*/
1901
static int
1902
icmp6_rip6_input(struct mbuf **mp, int off)
1903
{
1904
struct mbuf *n, *m = *mp;
1905
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1906
struct inpcb_iterator inpi = INP_ITERATOR(&V_ripcbinfo,
1907
INPLOOKUP_RLOCKPCB, icmp6_rip6_match, ip6);
1908
struct inpcb *inp;
1909
struct sockaddr_in6 fromsa;
1910
struct icmp6_hdr *icmp6;
1911
struct mbuf *opts = NULL;
1912
int delivered = 0, fib;
1913
1914
/* This is assumed to be safe; icmp6_input() does a pullup. */
1915
icmp6 = (struct icmp6_hdr *)((caddr_t)ip6 + off);
1916
1917
/*
1918
* XXX: the address may have embedded scope zone ID, which should be
1919
* hidden from applications.
1920
*/
1921
bzero(&fromsa, sizeof(fromsa));
1922
fromsa.sin6_family = AF_INET6;
1923
fromsa.sin6_len = sizeof(struct sockaddr_in6);
1924
fromsa.sin6_addr = ip6->ip6_src;
1925
if (sa6_recoverscope(&fromsa)) {
1926
m_freem(m);
1927
*mp = NULL;
1928
return (IPPROTO_DONE);
1929
}
1930
1931
fib = M_GETFIB(m);
1932
1933
while ((inp = inp_next(&inpi)) != NULL) {
1934
if (V_rip_bind_all_fibs == 0 && fib != inp->inp_inc.inc_fibnum)
1935
/*
1936
* Sockets bound to a specific FIB can only receive
1937
* packets from that FIB.
1938
*/
1939
continue;
1940
if (ICMP6_FILTER_WILLBLOCK(icmp6->icmp6_type,
1941
inp->in6p_icmp6filt))
1942
continue;
1943
/*
1944
* Recent network drivers tend to allocate a single
1945
* mbuf cluster, rather than to make a couple of
1946
* mbufs without clusters. Also, since the IPv6 code
1947
* path tries to avoid m_pullup(), it is highly
1948
* probable that we still have an mbuf cluster here
1949
* even though the necessary length can be stored in an
1950
* mbuf's internal buffer.
1951
* Meanwhile, the default size of the receive socket
1952
* buffer for raw sockets is not so large. This means
1953
* the possibility of packet loss is relatively higher
1954
* than before. To avoid this scenario, we copy the
1955
* received data to a separate mbuf that does not use
1956
* a cluster, if possible.
1957
* XXX: it is better to copy the data after stripping
1958
* intermediate headers.
1959
*/
1960
if ((m->m_flags & M_EXT) && m->m_next == NULL &&
1961
m->m_len <= MHLEN) {
1962
n = m_get(M_NOWAIT, m->m_type);
1963
if (n != NULL) {
1964
if (m_dup_pkthdr(n, m, M_NOWAIT)) {
1965
bcopy(m->m_data, n->m_data, m->m_len);
1966
n->m_len = m->m_len;
1967
} else {
1968
m_free(n);
1969
n = NULL;
1970
}
1971
}
1972
} else
1973
n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
1974
if (n == NULL)
1975
continue;
1976
if (inp->inp_flags & INP_CONTROLOPTS)
1977
ip6_savecontrol(inp, n, &opts);
1978
/* strip intermediate headers */
1979
m_adj(n, off);
1980
SOCKBUF_LOCK(&inp->inp_socket->so_rcv);
1981
if (sbappendaddr_locked(&inp->inp_socket->so_rcv,
1982
(struct sockaddr *)&fromsa, n, opts) == 0) {
1983
soroverflow_locked(inp->inp_socket);
1984
m_freem(n);
1985
if (opts)
1986
m_freem(opts);
1987
} else {
1988
sorwakeup_locked(inp->inp_socket);
1989
delivered++;
1990
}
1991
opts = NULL;
1992
}
1993
m_freem(m);
1994
*mp = NULL;
1995
if (delivered == 0)
1996
IP6STAT_DEC(ip6s_delivered);
1997
return (IPPROTO_DONE);
1998
}
1999
2000
/*
2001
* Reflect the ip6 packet back to the source.
2002
* OFF points to the icmp6 header, counted from the top of the mbuf.
2003
*/
2004
static void
2005
icmp6_reflect(struct mbuf *m, size_t off)
2006
{
2007
struct in6_addr src6, *srcp;
2008
struct ip6_hdr *ip6;
2009
struct icmp6_hdr *icmp6;
2010
struct in6_ifaddr *ia = NULL;
2011
struct ifnet *outif = NULL;
2012
int plen;
2013
int type, code, hlim;
2014
2015
/* too short to reflect */
2016
if (off < sizeof(struct ip6_hdr)) {
2017
nd6log((LOG_DEBUG,
2018
"sanity fail: off=%lx, sizeof(ip6)=%lx in %s:%d\n",
2019
(u_long)off, (u_long)sizeof(struct ip6_hdr),
2020
__FILE__, __LINE__));
2021
goto bad;
2022
}
2023
2024
/*
2025
* If there are extra headers between IPv6 and ICMPv6, strip
2026
* off that header first.
2027
*/
2028
#ifdef DIAGNOSTIC
2029
if (sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) > MHLEN)
2030
panic("assumption failed in icmp6_reflect");
2031
#endif
2032
if (off > sizeof(struct ip6_hdr)) {
2033
size_t l;
2034
struct ip6_hdr nip6;
2035
2036
l = off - sizeof(struct ip6_hdr);
2037
m_copydata(m, 0, sizeof(nip6), (caddr_t)&nip6);
2038
m_adj(m, l);
2039
l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
2040
if (m->m_len < l) {
2041
if ((m = m_pullup(m, l)) == NULL)
2042
return;
2043
}
2044
bcopy((caddr_t)&nip6, mtod(m, caddr_t), sizeof(nip6));
2045
} else /* off == sizeof(struct ip6_hdr) */ {
2046
size_t l;
2047
l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
2048
if (m->m_len < l) {
2049
if ((m = m_pullup(m, l)) == NULL)
2050
return;
2051
}
2052
}
2053
plen = m->m_pkthdr.len - sizeof(struct ip6_hdr);
2054
ip6 = mtod(m, struct ip6_hdr *);
2055
ip6->ip6_nxt = IPPROTO_ICMPV6;
2056
icmp6 = (struct icmp6_hdr *)(ip6 + 1);
2057
type = icmp6->icmp6_type; /* keep type for statistics */
2058
code = icmp6->icmp6_code; /* ditto. */
2059
hlim = 0;
2060
srcp = NULL;
2061
2062
if (__predict_false(IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src))) {
2063
nd6log((LOG_DEBUG,
2064
"icmp6_reflect: source address is unspecified\n"));
2065
goto bad;
2066
}
2067
2068
/*
2069
* If the incoming packet was addressed directly to us (i.e. unicast),
2070
* use dst as the src for the reply.
2071
* The IN6_IFF_NOTREADY case should be VERY rare, but is possible
2072
* (for example) when we encounter an error while forwarding procedure
2073
* destined to a duplicated address of ours.
2074
*/
2075
if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
2076
ia = in6ifa_ifwithaddr(&ip6->ip6_dst, 0 /* XXX */, false);
2077
if (ia != NULL && !(ia->ia6_flags &
2078
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY))) {
2079
src6 = ia->ia_addr.sin6_addr;
2080
srcp = &src6;
2081
2082
if (m->m_pkthdr.rcvif != NULL) {
2083
/* XXX: This may not be the outgoing interface */
2084
hlim = ND_IFINFO(m->m_pkthdr.rcvif)->chlim;
2085
} else
2086
hlim = V_ip6_defhlim;
2087
}
2088
}
2089
2090
if (srcp == NULL) {
2091
int error;
2092
struct in6_addr dst6;
2093
uint32_t scopeid;
2094
2095
/*
2096
* This case matches to multicasts, our anycast, or unicasts
2097
* that we do not own. Select a source address based on the
2098
* source address of the erroneous packet.
2099
*/
2100
in6_splitscope(&ip6->ip6_src, &dst6, &scopeid);
2101
error = in6_selectsrc_addr(M_GETFIB(m), &dst6,
2102
scopeid, NULL, &src6, &hlim);
2103
2104
if (error) {
2105
char ip6buf[INET6_ADDRSTRLEN];
2106
nd6log((LOG_DEBUG,
2107
"icmp6_reflect: source can't be determined: "
2108
"dst=%s, error=%d\n",
2109
ip6_sprintf(ip6buf, &ip6->ip6_dst), error));
2110
goto bad;
2111
}
2112
srcp = &src6;
2113
}
2114
/*
2115
* ip6_input() drops a packet if its src is multicast.
2116
* So, the src is never multicast.
2117
*/
2118
ip6->ip6_dst = ip6->ip6_src;
2119
ip6->ip6_src = *srcp;
2120
ip6->ip6_flow = 0;
2121
ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
2122
ip6->ip6_vfc |= IPV6_VERSION;
2123
ip6->ip6_nxt = IPPROTO_ICMPV6;
2124
ip6->ip6_hlim = hlim;
2125
2126
icmp6->icmp6_cksum = 0;
2127
icmp6->icmp6_cksum = in6_cksum(m, IPPROTO_ICMPV6,
2128
sizeof(struct ip6_hdr), plen);
2129
2130
/*
2131
* XXX option handling
2132
*/
2133
2134
m->m_flags &= ~(M_BCAST|M_MCAST);
2135
m->m_pkthdr.rcvif = NULL;
2136
ip6_output(m, NULL, NULL, 0, NULL, &outif, NULL);
2137
if (outif)
2138
icmp6_ifoutstat_inc(outif, type, code);
2139
2140
return;
2141
2142
bad:
2143
m_freem(m);
2144
return;
2145
}
2146
2147
static const char *
2148
icmp6_redirect_diag(struct in6_addr *src6, struct in6_addr *dst6,
2149
struct in6_addr *tgt6)
2150
{
2151
static char buf[1024];
2152
char ip6bufs[INET6_ADDRSTRLEN];
2153
char ip6bufd[INET6_ADDRSTRLEN];
2154
char ip6buft[INET6_ADDRSTRLEN];
2155
snprintf(buf, sizeof(buf), "(src=%s dst=%s tgt=%s)",
2156
ip6_sprintf(ip6bufs, src6), ip6_sprintf(ip6bufd, dst6),
2157
ip6_sprintf(ip6buft, tgt6));
2158
return buf;
2159
}
2160
2161
void
2162
icmp6_redirect_input(struct mbuf *m, int off)
2163
{
2164
struct ifnet *ifp;
2165
struct ip6_hdr *ip6;
2166
struct nd_redirect *nd_rd;
2167
struct in6_addr src6, redtgt6, reddst6;
2168
union nd_opts ndopts;
2169
char ip6buf[INET6_ADDRSTRLEN];
2170
char *lladdr;
2171
int icmp6len, is_onlink, is_router, lladdrlen;
2172
2173
M_ASSERTPKTHDR(m);
2174
KASSERT(m->m_pkthdr.rcvif != NULL, ("%s: no rcvif", __func__));
2175
2176
/* XXX if we are router, we don't update route by icmp6 redirect */
2177
if (V_ip6_forwarding)
2178
goto freeit;
2179
if (!V_icmp6_rediraccept)
2180
goto freeit;
2181
2182
/* RFC 6980: Nodes MUST silently ignore fragments */
2183
if(m->m_flags & M_FRAGMENTED)
2184
goto freeit;
2185
2186
ip6 = mtod(m, struct ip6_hdr *);
2187
icmp6len = ntohs(ip6->ip6_plen);
2188
if (m->m_len < off + icmp6len) {
2189
m = m_pullup(m, off + icmp6len);
2190
if (m == NULL) {
2191
IP6STAT_INC(ip6s_exthdrtoolong);
2192
return;
2193
}
2194
}
2195
ip6 = mtod(m, struct ip6_hdr *);
2196
nd_rd = (struct nd_redirect *)((caddr_t)ip6 + off);
2197
2198
ifp = m->m_pkthdr.rcvif;
2199
redtgt6 = nd_rd->nd_rd_target;
2200
reddst6 = nd_rd->nd_rd_dst;
2201
2202
if (in6_setscope(&redtgt6, ifp, NULL) ||
2203
in6_setscope(&reddst6, ifp, NULL)) {
2204
goto freeit;
2205
}
2206
2207
/* validation */
2208
src6 = ip6->ip6_src;
2209
if (!IN6_IS_ADDR_LINKLOCAL(&src6)) {
2210
nd6log((LOG_ERR,
2211
"ICMP6 redirect sent from %s rejected; "
2212
"must be from linklocal\n",
2213
ip6_sprintf(ip6buf, &src6)));
2214
goto bad;
2215
}
2216
if (__predict_false(ip6->ip6_hlim != 255)) {
2217
ICMP6STAT_INC(icp6s_invlhlim);
2218
nd6log((LOG_ERR,
2219
"ICMP6 redirect sent from %s rejected; "
2220
"hlim=%d (must be 255)\n",
2221
ip6_sprintf(ip6buf, &src6), ip6->ip6_hlim));
2222
goto bad;
2223
}
2224
{
2225
/* ip6->ip6_src must be equal to gw for icmp6->icmp6_reddst */
2226
struct nhop_object *nh;
2227
struct in6_addr kdst;
2228
uint32_t scopeid;
2229
2230
in6_splitscope(&reddst6, &kdst, &scopeid);
2231
NET_EPOCH_ASSERT();
2232
nh = fib6_lookup(ifp->if_fib, &kdst, scopeid, 0, 0);
2233
if (nh != NULL) {
2234
struct in6_addr nh_addr;
2235
nh_addr = ifatoia6(nh->nh_ifa)->ia_addr.sin6_addr;
2236
if ((nh->nh_flags & NHF_GATEWAY) == 0) {
2237
nd6log((LOG_ERR,
2238
"ICMP6 redirect rejected; no route "
2239
"with inet6 gateway found for redirect dst: %s\n",
2240
icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
2241
goto bad;
2242
}
2243
2244
/*
2245
* Embed scope zone id into next hop address.
2246
*/
2247
nh_addr = nh->gw6_sa.sin6_addr;
2248
2249
if (IN6_ARE_ADDR_EQUAL(&src6, &nh_addr) == 0) {
2250
nd6log((LOG_ERR,
2251
"ICMP6 redirect rejected; "
2252
"not equal to gw-for-src=%s (must be same): "
2253
"%s\n",
2254
ip6_sprintf(ip6buf, &nh_addr),
2255
icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
2256
goto bad;
2257
}
2258
} else {
2259
nd6log((LOG_ERR,
2260
"ICMP6 redirect rejected; "
2261
"no route found for redirect dst: %s\n",
2262
icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
2263
goto bad;
2264
}
2265
}
2266
if (IN6_IS_ADDR_MULTICAST(&reddst6)) {
2267
nd6log((LOG_ERR,
2268
"ICMP6 redirect rejected; "
2269
"redirect dst must be unicast: %s\n",
2270
icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
2271
goto bad;
2272
}
2273
2274
is_router = is_onlink = 0;
2275
if (IN6_IS_ADDR_LINKLOCAL(&redtgt6))
2276
is_router = 1; /* router case */
2277
if (bcmp(&redtgt6, &reddst6, sizeof(redtgt6)) == 0)
2278
is_onlink = 1; /* on-link destination case */
2279
if (!is_router && !is_onlink) {
2280
nd6log((LOG_ERR,
2281
"ICMP6 redirect rejected; "
2282
"neither router case nor onlink case: %s\n",
2283
icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
2284
goto bad;
2285
}
2286
2287
icmp6len -= sizeof(*nd_rd);
2288
nd6_option_init(nd_rd + 1, icmp6len, &ndopts);
2289
if (nd6_options(&ndopts) < 0) {
2290
nd6log((LOG_INFO, "%s: invalid ND option, rejected: %s\n",
2291
__func__, icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
2292
/* nd6_options have incremented stats */
2293
goto freeit;
2294
}
2295
2296
lladdr = NULL;
2297
lladdrlen = 0;
2298
if (ndopts.nd_opts_tgt_lladdr) {
2299
lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1);
2300
lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
2301
}
2302
2303
if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
2304
nd6log((LOG_INFO, "%s: lladdrlen mismatch for %s "
2305
"(if %d, icmp6 packet %d): %s\n",
2306
__func__, ip6_sprintf(ip6buf, &redtgt6),
2307
ifp->if_addrlen, lladdrlen - 2,
2308
icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
2309
goto bad;
2310
}
2311
2312
/* Validation passed. */
2313
2314
/* RFC 2461 8.3 */
2315
nd6_cache_lladdr(ifp, &redtgt6, lladdr, lladdrlen, ND_REDIRECT,
2316
is_onlink ? ND_REDIRECT_ONLINK : ND_REDIRECT_ROUTER);
2317
2318
/*
2319
* Install a gateway route in the better-router case or an interface
2320
* route in the on-link-destination case.
2321
*/
2322
{
2323
struct sockaddr_in6 sdst;
2324
struct sockaddr_in6 sgw;
2325
struct sockaddr_in6 ssrc;
2326
struct sockaddr *gw;
2327
int rt_flags;
2328
u_int fibnum;
2329
2330
bzero(&sdst, sizeof(sdst));
2331
bzero(&ssrc, sizeof(ssrc));
2332
sdst.sin6_family = ssrc.sin6_family = AF_INET6;
2333
sdst.sin6_len = ssrc.sin6_len = sizeof(struct sockaddr_in6);
2334
bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr));
2335
bcopy(&src6, &ssrc.sin6_addr, sizeof(struct in6_addr));
2336
rt_flags = 0;
2337
if (is_router) {
2338
bzero(&sgw, sizeof(sgw));
2339
sgw.sin6_family = AF_INET6;
2340
sgw.sin6_len = sizeof(struct sockaddr_in6);
2341
bcopy(&redtgt6, &sgw.sin6_addr,
2342
sizeof(struct in6_addr));
2343
gw = (struct sockaddr *)&sgw;
2344
rt_flags |= RTF_GATEWAY;
2345
} else
2346
gw = ifp->if_addr->ifa_addr;
2347
for (fibnum = 0; fibnum < rt_numfibs; fibnum++)
2348
rib_add_redirect(fibnum, (struct sockaddr *)&sdst, gw,
2349
(struct sockaddr *)&ssrc, ifp, rt_flags,
2350
V_icmp6_redirtimeout);
2351
}
2352
2353
freeit:
2354
m_freem(m);
2355
return;
2356
2357
bad:
2358
ICMP6STAT_INC(icp6s_badredirect);
2359
m_freem(m);
2360
}
2361
2362
void
2363
icmp6_redirect_output(struct mbuf *m0, struct nhop_object *nh)
2364
{
2365
struct ifnet *ifp; /* my outgoing interface */
2366
struct in6_addr ifp_ll6;
2367
struct in6_addr *router_ll6;
2368
struct ip6_hdr *sip6; /* m0 as struct ip6_hdr */
2369
struct mbuf *m = NULL; /* newly allocated one */
2370
struct m_tag *mtag;
2371
struct ip6_hdr *ip6; /* m as struct ip6_hdr */
2372
struct nd_redirect *nd_rd;
2373
struct llentry *ln = NULL;
2374
size_t maxlen;
2375
u_char *p;
2376
struct ifnet *outif = NULL;
2377
struct sockaddr_in6 src_sa;
2378
2379
icmp6_errcount(ND_REDIRECT, 0);
2380
2381
/* if we are not router, we don't send icmp6 redirect */
2382
if (!V_ip6_forwarding)
2383
goto fail;
2384
2385
/* sanity check */
2386
if (!m0 || !nh || !(NH_IS_VALID(nh)) || !(ifp = nh->nh_ifp))
2387
goto fail;
2388
2389
/*
2390
* Address check:
2391
* the source address must identify a neighbor, and
2392
* the destination address must not be a multicast address
2393
* [RFC 2461, sec 8.2]
2394
*/
2395
sip6 = mtod(m0, struct ip6_hdr *);
2396
bzero(&src_sa, sizeof(src_sa));
2397
src_sa.sin6_family = AF_INET6;
2398
src_sa.sin6_len = sizeof(src_sa);
2399
src_sa.sin6_addr = sip6->ip6_src;
2400
if (nd6_is_addr_neighbor(&src_sa, ifp) == 0)
2401
goto fail;
2402
if (IN6_IS_ADDR_MULTICAST(&sip6->ip6_dst))
2403
goto fail; /* what should we do here? */
2404
2405
/* rate limit */
2406
if (icmp6_ratelimit(&sip6->ip6_src, ND_REDIRECT, 0))
2407
goto fail;
2408
2409
/*
2410
* Since we are going to append up to 1280 bytes (= IPV6_MMTU),
2411
* we almost always ask for an mbuf cluster for simplicity.
2412
* (MHLEN < IPV6_MMTU is almost always true)
2413
*/
2414
#if IPV6_MMTU >= MCLBYTES
2415
# error assumption failed about IPV6_MMTU and MCLBYTES
2416
#endif
2417
m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
2418
if (m == NULL)
2419
goto fail;
2420
M_SETFIB(m, M_GETFIB(m0));
2421
maxlen = M_TRAILINGSPACE(m);
2422
maxlen = min(IPV6_MMTU, maxlen);
2423
/* just for safety */
2424
if (maxlen < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) +
2425
((sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7)) {
2426
goto fail;
2427
}
2428
2429
{
2430
/* get ip6 linklocal address for ifp(my outgoing interface). */
2431
struct in6_ifaddr *ia;
2432
if ((ia = in6ifa_ifpforlinklocal(ifp,
2433
IN6_IFF_NOTREADY|
2434
IN6_IFF_ANYCAST)) == NULL)
2435
goto fail;
2436
bcopy(&ia->ia_addr.sin6_addr, &ifp_ll6, sizeof(ifp_ll6));
2437
ifa_free(&ia->ia_ifa);
2438
}
2439
2440
/* get ip6 linklocal address for the router. */
2441
if (nh->nh_flags & NHF_GATEWAY) {
2442
struct sockaddr_in6 *sin6;
2443
sin6 = &nh->gw6_sa;
2444
router_ll6 = &sin6->sin6_addr;
2445
if (!IN6_IS_ADDR_LINKLOCAL(router_ll6))
2446
router_ll6 = (struct in6_addr *)NULL;
2447
} else
2448
router_ll6 = (struct in6_addr *)NULL;
2449
2450
/* ip6 */
2451
ip6 = mtod(m, struct ip6_hdr *);
2452
ip6->ip6_flow = 0;
2453
ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
2454
ip6->ip6_vfc |= IPV6_VERSION;
2455
/* ip6->ip6_plen will be set later */
2456
ip6->ip6_nxt = IPPROTO_ICMPV6;
2457
ip6->ip6_hlim = 255;
2458
/* ip6->ip6_src must be linklocal addr for my outgoing if. */
2459
bcopy(&ifp_ll6, &ip6->ip6_src, sizeof(struct in6_addr));
2460
bcopy(&sip6->ip6_src, &ip6->ip6_dst, sizeof(struct in6_addr));
2461
2462
/* ND Redirect */
2463
nd_rd = (struct nd_redirect *)(ip6 + 1);
2464
nd_rd->nd_rd_type = ND_REDIRECT;
2465
nd_rd->nd_rd_code = 0;
2466
nd_rd->nd_rd_reserved = 0;
2467
if (nh->nh_flags & NHF_GATEWAY) {
2468
/*
2469
* nd_rd->nd_rd_target must be a link-local address in
2470
* better router cases.
2471
*/
2472
if (!router_ll6)
2473
goto fail;
2474
bcopy(router_ll6, &nd_rd->nd_rd_target,
2475
sizeof(nd_rd->nd_rd_target));
2476
bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst,
2477
sizeof(nd_rd->nd_rd_dst));
2478
} else {
2479
/* make sure redtgt == reddst */
2480
bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_target,
2481
sizeof(nd_rd->nd_rd_target));
2482
bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst,
2483
sizeof(nd_rd->nd_rd_dst));
2484
}
2485
2486
p = (u_char *)(nd_rd + 1);
2487
2488
if (!router_ll6)
2489
goto nolladdropt;
2490
2491
{
2492
/* target lladdr option */
2493
int len;
2494
struct nd_opt_hdr *nd_opt;
2495
char *lladdr;
2496
2497
ln = nd6_lookup(router_ll6, LLE_SF(AF_INET6, 0), ifp);
2498
if (ln == NULL)
2499
goto nolladdropt;
2500
2501
len = sizeof(*nd_opt) + ifp->if_addrlen;
2502
len = (len + 7) & ~7; /* round by 8 */
2503
/* safety check */
2504
if (len + (p - (u_char *)ip6) > maxlen)
2505
goto nolladdropt;
2506
2507
if (ln->la_flags & LLE_VALID) {
2508
nd_opt = (struct nd_opt_hdr *)p;
2509
nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
2510
nd_opt->nd_opt_len = len >> 3;
2511
lladdr = (char *)(nd_opt + 1);
2512
bcopy(ln->ll_addr, lladdr, ifp->if_addrlen);
2513
p += len;
2514
}
2515
}
2516
nolladdropt:
2517
if (ln != NULL)
2518
LLE_RUNLOCK(ln);
2519
2520
m->m_pkthdr.len = m->m_len = p - (u_char *)ip6;
2521
2522
/* just to be safe */
2523
#ifdef M_DECRYPTED /*not openbsd*/
2524
if (m0->m_flags & M_DECRYPTED)
2525
goto noredhdropt;
2526
#endif
2527
if (p - (u_char *)ip6 > maxlen)
2528
goto noredhdropt;
2529
2530
{
2531
/* redirected header option */
2532
int len;
2533
struct nd_opt_rd_hdr *nd_opt_rh;
2534
2535
/*
2536
* compute the maximum size for icmp6 redirect header option.
2537
* XXX room for auth header?
2538
*/
2539
len = maxlen - (p - (u_char *)ip6);
2540
len &= ~7;
2541
2542
/* This is just for simplicity. */
2543
if (m0->m_pkthdr.len != m0->m_len) {
2544
if (m0->m_next) {
2545
m_freem(m0->m_next);
2546
m0->m_next = NULL;
2547
}
2548
m0->m_pkthdr.len = m0->m_len;
2549
}
2550
2551
/*
2552
* Redirected header option spec (RFC2461 4.6.3) talks nothing
2553
* about padding/truncate rule for the original IP packet.
2554
* From the discussion on IPv6imp in Feb 1999,
2555
* the consensus was:
2556
* - "attach as much as possible" is the goal
2557
* - pad if not aligned (original size can be guessed by
2558
* original ip6 header)
2559
* Following code adds the padding if it is simple enough,
2560
* and truncates if not.
2561
*/
2562
if (m0->m_next || m0->m_pkthdr.len != m0->m_len)
2563
panic("assumption failed in %s:%d", __FILE__,
2564
__LINE__);
2565
2566
if (len - sizeof(*nd_opt_rh) < m0->m_pkthdr.len) {
2567
/* not enough room, truncate */
2568
m0->m_pkthdr.len = m0->m_len = len -
2569
sizeof(*nd_opt_rh);
2570
} else {
2571
/* enough room, pad or truncate */
2572
size_t extra;
2573
2574
extra = m0->m_pkthdr.len % 8;
2575
if (extra) {
2576
/* pad if easy enough, truncate if not */
2577
if (8 - extra <= M_TRAILINGSPACE(m0)) {
2578
/* pad */
2579
bzero(m0->m_data + m0->m_len, 8 - extra);
2580
m0->m_len += (8 - extra);
2581
m0->m_pkthdr.len += (8 - extra);
2582
} else {
2583
/* truncate */
2584
m0->m_pkthdr.len -= extra;
2585
m0->m_len -= extra;
2586
}
2587
}
2588
len = m0->m_pkthdr.len + sizeof(*nd_opt_rh);
2589
m0->m_pkthdr.len = m0->m_len = len -
2590
sizeof(*nd_opt_rh);
2591
}
2592
2593
nd_opt_rh = (struct nd_opt_rd_hdr *)p;
2594
bzero(nd_opt_rh, sizeof(*nd_opt_rh));
2595
nd_opt_rh->nd_opt_rh_type = ND_OPT_REDIRECTED_HEADER;
2596
nd_opt_rh->nd_opt_rh_len = len >> 3;
2597
p += sizeof(*nd_opt_rh);
2598
m->m_pkthdr.len = m->m_len = p - (u_char *)ip6;
2599
2600
/* connect m0 to m */
2601
m_tag_delete_chain(m0, NULL);
2602
m0->m_flags &= ~M_PKTHDR;
2603
m->m_next = m0;
2604
m->m_pkthdr.len = m->m_len + m0->m_len;
2605
m0 = NULL;
2606
}
2607
noredhdropt:;
2608
if (m0) {
2609
m_freem(m0);
2610
m0 = NULL;
2611
}
2612
2613
/* XXX: clear embedded link IDs in the inner header */
2614
in6_clearscope(&sip6->ip6_src);
2615
in6_clearscope(&sip6->ip6_dst);
2616
in6_clearscope(&nd_rd->nd_rd_target);
2617
in6_clearscope(&nd_rd->nd_rd_dst);
2618
2619
ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
2620
2621
nd_rd->nd_rd_cksum = 0;
2622
nd_rd->nd_rd_cksum = in6_cksum(m, IPPROTO_ICMPV6,
2623
sizeof(*ip6), ntohs(ip6->ip6_plen));
2624
2625
if (send_sendso_input_hook != NULL) {
2626
mtag = m_tag_get(PACKET_TAG_ND_OUTGOING, sizeof(unsigned short),
2627
M_NOWAIT);
2628
if (mtag == NULL)
2629
goto fail;
2630
*(unsigned short *)(mtag + 1) = nd_rd->nd_rd_type;
2631
m_tag_prepend(m, mtag);
2632
}
2633
2634
/* send the packet to outside... */
2635
ip6_output(m, NULL, NULL, 0, NULL, &outif, NULL);
2636
if (outif) {
2637
icmp6_ifstat_inc(outif, ifs6_out_msg);
2638
icmp6_ifstat_inc(outif, ifs6_out_redirect);
2639
}
2640
ICMP6STAT_INC2(icp6s_outhist, ND_REDIRECT);
2641
2642
return;
2643
2644
fail:
2645
if (m)
2646
m_freem(m);
2647
if (m0)
2648
m_freem(m0);
2649
}
2650
2651
/*
2652
* ICMPv6 socket option processing.
2653
*/
2654
int
2655
icmp6_ctloutput(struct socket *so, struct sockopt *sopt)
2656
{
2657
int error = 0;
2658
int optlen;
2659
struct inpcb *inp = sotoinpcb(so);
2660
int level, op, optname;
2661
2662
if (sopt) {
2663
level = sopt->sopt_level;
2664
op = sopt->sopt_dir;
2665
optname = sopt->sopt_name;
2666
optlen = sopt->sopt_valsize;
2667
} else
2668
level = op = optname = optlen = 0;
2669
2670
if (level != IPPROTO_ICMPV6) {
2671
return EINVAL;
2672
}
2673
2674
switch (op) {
2675
case SOPT_SET:
2676
switch (optname) {
2677
case ICMP6_FILTER:
2678
{
2679
struct icmp6_filter ic6f;
2680
2681
if (optlen != sizeof(ic6f)) {
2682
error = EMSGSIZE;
2683
break;
2684
}
2685
error = sooptcopyin(sopt, &ic6f, optlen, optlen);
2686
if (error == 0) {
2687
INP_WLOCK(inp);
2688
*inp->in6p_icmp6filt = ic6f;
2689
INP_WUNLOCK(inp);
2690
}
2691
break;
2692
}
2693
2694
default:
2695
error = ENOPROTOOPT;
2696
break;
2697
}
2698
break;
2699
2700
case SOPT_GET:
2701
switch (optname) {
2702
case ICMP6_FILTER:
2703
{
2704
struct icmp6_filter ic6f;
2705
2706
INP_RLOCK(inp);
2707
ic6f = *inp->in6p_icmp6filt;
2708
INP_RUNLOCK(inp);
2709
error = sooptcopyout(sopt, &ic6f, sizeof(ic6f));
2710
break;
2711
}
2712
2713
default:
2714
error = ENOPROTOOPT;
2715
break;
2716
}
2717
break;
2718
}
2719
2720
return (error);
2721
}
2722
2723
static int sysctl_icmp6lim_and_jitter(SYSCTL_HANDLER_ARGS);
2724
VNET_DEFINE_STATIC(u_int, icmp6errppslim) = 100;
2725
#define V_icmp6errppslim VNET(icmp6errppslim)
2726
SYSCTL_PROC(_net_inet6_icmp6, ICMPV6CTL_ERRPPSLIMIT, errppslimit,
2727
CTLTYPE_UINT | CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(icmp6errppslim), 0,
2728
&sysctl_icmp6lim_and_jitter, "IU",
2729
"Maximum number of ICMPv6 error/reply messages per second");
2730
2731
typedef enum {
2732
RATELIM_PARAM_PROB = 0,
2733
RATELIM_TOO_BIG,
2734
RATELIM_UNREACH,
2735
RATELIM_TEXCEED,
2736
RATELIM_REDIR,
2737
RATELIM_REPLY,
2738
RATELIM_OTHER,
2739
RATELIM_MAX
2740
} ratelim_which;
2741
2742
static const char *icmp6_rate_descrs[RATELIM_MAX] = {
2743
[RATELIM_PARAM_PROB] = "bad IPv6 header",
2744
[RATELIM_TOO_BIG] = "packet too big",
2745
[RATELIM_UNREACH] = "destination unreachable",
2746
[RATELIM_TEXCEED] = "time exceeded",
2747
[RATELIM_REPLY] = "echo reply",
2748
[RATELIM_REDIR] = "neighbor discovery redirect",
2749
[RATELIM_OTHER] = "(other)",
2750
};
2751
2752
VNET_DEFINE_STATIC(int, icmp6lim_curr_jitter[RATELIM_MAX]) = {0};
2753
#define V_icmp6lim_curr_jitter VNET(icmp6lim_curr_jitter)
2754
2755
VNET_DEFINE_STATIC(u_int, icmp6lim_jitter) = 8;
2756
#define V_icmp6lim_jitter VNET(icmp6lim_jitter)
2757
SYSCTL_PROC(_net_inet6_icmp6, OID_AUTO, icmp6lim_jitter, CTLTYPE_UINT |
2758
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(icmp6lim_jitter), 0,
2759
&sysctl_icmp6lim_and_jitter, "IU",
2760
"Random errppslimit jitter adjustment limit");
2761
2762
VNET_DEFINE_STATIC(int, icmp6lim_output) = 1;
2763
#define V_icmp6lim_output VNET(icmp6lim_output)
2764
SYSCTL_INT(_net_inet6_icmp6, OID_AUTO, icmp6lim_output,
2765
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(icmp6lim_output), 0,
2766
"Enable logging of ICMPv6 response rate limiting");
2767
2768
static void
2769
icmp6lim_new_jitter(int which)
2770
{
2771
/*
2772
* Adjust limit +/- to jitter the measurement to deny a side-channel
2773
* port scan as in https://dl.acm.org/doi/10.1145/3372297.3417280
2774
*/
2775
KASSERT(which >= 0 && which < RATELIM_MAX,
2776
("%s: which %d", __func__, which));
2777
if (V_icmp6lim_jitter > 0)
2778
V_icmp6lim_curr_jitter[which] =
2779
arc4random_uniform(V_icmp6lim_jitter * 2 + 1) -
2780
V_icmp6lim_jitter;
2781
}
2782
2783
static int
2784
sysctl_icmp6lim_and_jitter(SYSCTL_HANDLER_ARGS)
2785
{
2786
uint32_t new;
2787
int error;
2788
bool lim;
2789
2790
MPASS(oidp->oid_arg1 == &VNET_NAME(icmp6errppslim) ||
2791
oidp->oid_arg1 == &VNET_NAME(icmp6lim_jitter));
2792
2793
lim = (oidp->oid_arg1 == &VNET_NAME(icmp6errppslim));
2794
new = lim ? V_icmp6errppslim : V_icmp6lim_jitter;
2795
error = sysctl_handle_int(oidp, &new, 0, req);
2796
if (error == 0 && req->newptr) {
2797
if (lim) {
2798
if (new != 0 && new <= V_icmp6lim_jitter)
2799
error = EINVAL;
2800
else
2801
V_icmp6errppslim = new;
2802
} else {
2803
if (new >= V_icmp6errppslim)
2804
error = EINVAL;
2805
else {
2806
V_icmp6lim_jitter = new;
2807
for (int i = 0; i < RATELIM_MAX; i++) {
2808
icmp6lim_new_jitter(i);
2809
}
2810
}
2811
}
2812
}
2813
MPASS(V_icmp6errppslim == 0 || V_icmp6errppslim > V_icmp6lim_jitter);
2814
2815
return (error);
2816
}
2817
2818
2819
VNET_DEFINE_STATIC(struct counter_rate *, icmp6_rates[RATELIM_MAX]);
2820
#define V_icmp6_rates VNET(icmp6_rates)
2821
2822
static void
2823
icmp6_ratelimit_init(void)
2824
{
2825
2826
for (int i = 0; i < RATELIM_MAX; i++) {
2827
V_icmp6_rates[i] = counter_rate_alloc(M_WAITOK, 1);
2828
icmp6lim_new_jitter(i);
2829
}
2830
}
2831
VNET_SYSINIT(icmp6_ratelimit, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY,
2832
icmp6_ratelimit_init, NULL);
2833
2834
#ifdef VIMAGE
2835
static void
2836
icmp6_ratelimit_uninit(void)
2837
{
2838
2839
for (int i = 0; i < RATELIM_MAX; i++)
2840
counter_rate_free(V_icmp6_rates[i]);
2841
}
2842
VNET_SYSUNINIT(icmp6_ratelimit, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD,
2843
icmp6_ratelimit_uninit, NULL);
2844
#endif
2845
2846
/*
2847
* Perform rate limit check.
2848
* Returns 0 if it is okay to send the icmp6 packet.
2849
* Returns 1 if the router SHOULD NOT send this icmp6 packet due to rate
2850
* limitation.
2851
*
2852
* XXX per-destination/type check necessary?
2853
*
2854
* dst - not used at this moment
2855
* code - not used at this moment
2856
*/
2857
int
2858
icmp6_ratelimit(const struct in6_addr *dst, const int type, const int code)
2859
{
2860
ratelim_which which;
2861
int64_t pps;
2862
2863
if (V_icmp6errppslim == 0)
2864
return (0);
2865
2866
switch (type) {
2867
case ICMP6_PARAM_PROB:
2868
which = RATELIM_PARAM_PROB;
2869
break;
2870
case ICMP6_PACKET_TOO_BIG:
2871
which = RATELIM_TOO_BIG;
2872
break;
2873
case ICMP6_DST_UNREACH:
2874
which = RATELIM_UNREACH;
2875
break;
2876
case ICMP6_TIME_EXCEEDED:
2877
which = RATELIM_TEXCEED;
2878
break;
2879
case ND_REDIRECT:
2880
which = RATELIM_REDIR;
2881
break;
2882
case ICMP6_ECHO_REPLY:
2883
which = RATELIM_REPLY;
2884
break;
2885
default:
2886
which = RATELIM_OTHER;
2887
break;
2888
};
2889
2890
pps = counter_ratecheck(V_icmp6_rates[which], V_icmp6errppslim +
2891
V_icmp6lim_curr_jitter[which]);
2892
if (pps > 0) {
2893
if (V_icmp6lim_output)
2894
log(LOG_NOTICE, "Limiting ICMPv6 %s output from %jd "
2895
"to %d packets/sec\n", icmp6_rate_descrs[which],
2896
(intmax_t )pps, V_icmp6errppslim +
2897
V_icmp6lim_curr_jitter[which]);
2898
icmp6lim_new_jitter(which);
2899
}
2900
if (pps == -1) {
2901
ICMP6STAT_INC(icp6s_toofreq);
2902
return (-1);
2903
}
2904
2905
return (0);
2906
}
2907
2908