Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/netinet6/icmp6.c
104120 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
#define MBUF_PRIVATE /* XXXRW: Optimisation tries to avoid M_EXT mbufs */
64
65
#include "opt_inet.h"
66
#include "opt_inet6.h"
67
68
#include <sys/param.h>
69
#include <sys/domain.h>
70
#include <sys/jail.h>
71
#include <sys/kernel.h>
72
#include <sys/lock.h>
73
#include <sys/malloc.h>
74
#include <sys/mbuf.h>
75
#include <sys/proc.h>
76
#include <sys/protosw.h>
77
#include <sys/signalvar.h>
78
#include <sys/socket.h>
79
#include <sys/socketvar.h>
80
#include <sys/sx.h>
81
#include <sys/syslog.h>
82
#include <sys/systm.h>
83
#include <sys/time.h>
84
85
#include <net/if.h>
86
#include <net/if_var.h>
87
#include <net/if_dl.h>
88
#include <net/if_llatbl.h>
89
#include <net/if_private.h>
90
#include <net/if_types.h>
91
#include <net/route.h>
92
#include <net/route/route_ctl.h>
93
#include <net/route/nhop.h>
94
#include <net/vnet.h>
95
96
#include <netinet/in.h>
97
#include <netinet/in_pcb.h>
98
#include <netinet/in_var.h>
99
#include <netinet/ip6.h>
100
#include <netinet/icmp6.h>
101
#include <netinet/tcp_var.h>
102
103
#include <netinet6/in6_fib.h>
104
#include <netinet6/in6_ifattach.h>
105
#include <netinet6/in6_pcb.h>
106
#include <netinet6/ip6_var.h>
107
#include <netinet6/scope6_var.h>
108
#include <netinet6/mld6_var.h>
109
#include <netinet6/nd6.h>
110
#include <netinet6/send.h>
111
112
extern ip6proto_ctlinput_t *ip6_ctlprotox[];
113
114
VNET_PCPUSTAT_DEFINE(struct icmp6stat, icmp6stat);
115
VNET_PCPUSTAT_SYSINIT(icmp6stat);
116
SYSCTL_VNET_PCPUSTAT(_net_inet6_icmp6, ICMPV6CTL_STATS, stats,
117
struct icmp6stat, icmp6stat,
118
"ICMPv6 statistics (struct icmp6stat, netinet/icmp6.h)");
119
120
#ifdef VIMAGE
121
VNET_PCPUSTAT_SYSUNINIT(icmp6stat);
122
#endif /* VIMAGE */
123
124
VNET_DEFINE_STATIC(int, icmp6_rediraccept) = 1;
125
#define V_icmp6_rediraccept VNET(icmp6_rediraccept)
126
SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_REDIRACCEPT, rediraccept,
127
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(icmp6_rediraccept), 0,
128
"Accept ICMPv6 redirect messages");
129
130
VNET_DEFINE_STATIC(int, icmp6_redirtimeout) = 10 * 60; /* 10 minutes */
131
#define V_icmp6_redirtimeout VNET(icmp6_redirtimeout)
132
SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_REDIRTIMEOUT, redirtimeout,
133
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(icmp6_redirtimeout), 0,
134
"Delay in seconds before expiring redirect route");
135
136
VNET_DEFINE_STATIC(int, icmp6_nodeinfo) = 0;
137
#define V_icmp6_nodeinfo VNET(icmp6_nodeinfo)
138
SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_NODEINFO, nodeinfo,
139
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(icmp6_nodeinfo), 0,
140
"Mask of enabled RFC4620 node information query types");
141
142
VNET_DECLARE(struct inpcbinfo, ripcbinfo);
143
#define V_ripcbinfo VNET(ripcbinfo)
144
145
VNET_DECLARE(int, rip_bind_all_fibs);
146
#define V_rip_bind_all_fibs VNET(rip_bind_all_fibs)
147
148
static void icmp6_errcount(int, int);
149
static int icmp6_rip6_input(struct mbuf **, int);
150
static void icmp6_reflect(struct mbuf *, size_t);
151
static const char *icmp6_redirect_diag(struct in6_addr *,
152
struct in6_addr *, struct in6_addr *);
153
static struct mbuf *ni6_input(struct mbuf *, int, struct prison *);
154
static struct mbuf *ni6_nametodns(const char *, int, int);
155
static int ni6_dnsmatch(const char *, int, const char *, int);
156
static int ni6_addrs(struct icmp6_nodeinfo *, struct mbuf *,
157
struct ifnet **, struct in6_addr *);
158
static int ni6_store_addrs(struct icmp6_nodeinfo *, struct icmp6_nodeinfo *,
159
struct ifnet *, int);
160
static int icmp6_notify_error(struct mbuf **, int, int);
161
static void icmp6_mtudisc_update(struct ip6ctlparam *ip6cp);
162
163
/*
164
* Kernel module interface for updating icmp6stat. The argument is an index
165
* into icmp6stat treated as an array of u_quad_t. While this encodes the
166
* general layout of icmp6stat into the caller, it doesn't encode its
167
* location, so that future changes to add, for example, per-CPU stats
168
* support won't cause binary compatibility problems for kernel modules.
169
*/
170
void
171
kmod_icmp6stat_inc(int statnum)
172
{
173
174
counter_u64_add(VNET(icmp6stat)[statnum], 1);
175
}
176
177
static void
178
icmp6_errcount(int type, int code)
179
{
180
switch (type) {
181
case ICMP6_DST_UNREACH:
182
switch (code) {
183
case ICMP6_DST_UNREACH_NOROUTE:
184
ICMP6STAT_INC(icp6s_odst_unreach_noroute);
185
return;
186
case ICMP6_DST_UNREACH_ADMIN:
187
ICMP6STAT_INC(icp6s_odst_unreach_admin);
188
return;
189
case ICMP6_DST_UNREACH_BEYONDSCOPE:
190
ICMP6STAT_INC(icp6s_odst_unreach_beyondscope);
191
return;
192
case ICMP6_DST_UNREACH_ADDR:
193
ICMP6STAT_INC(icp6s_odst_unreach_addr);
194
return;
195
case ICMP6_DST_UNREACH_NOPORT:
196
ICMP6STAT_INC(icp6s_odst_unreach_noport);
197
return;
198
}
199
break;
200
case ICMP6_PACKET_TOO_BIG:
201
ICMP6STAT_INC(icp6s_opacket_too_big);
202
return;
203
case ICMP6_TIME_EXCEEDED:
204
switch (code) {
205
case ICMP6_TIME_EXCEED_TRANSIT:
206
ICMP6STAT_INC(icp6s_otime_exceed_transit);
207
return;
208
case ICMP6_TIME_EXCEED_REASSEMBLY:
209
ICMP6STAT_INC(icp6s_otime_exceed_reassembly);
210
return;
211
}
212
break;
213
case ICMP6_PARAM_PROB:
214
switch (code) {
215
case ICMP6_PARAMPROB_HEADER:
216
ICMP6STAT_INC(icp6s_oparamprob_header);
217
return;
218
case ICMP6_PARAMPROB_NEXTHEADER:
219
ICMP6STAT_INC(icp6s_oparamprob_nextheader);
220
return;
221
case ICMP6_PARAMPROB_OPTION:
222
ICMP6STAT_INC(icp6s_oparamprob_option);
223
return;
224
}
225
break;
226
case ND_REDIRECT:
227
ICMP6STAT_INC(icp6s_oredirect);
228
return;
229
}
230
ICMP6STAT_INC(icp6s_ounknown);
231
}
232
233
/*
234
* A wrapper function for icmp6_error() necessary when the erroneous packet
235
* may not contain enough scope zone information.
236
*/
237
void
238
icmp6_error2(struct mbuf *m, int type, int code, int param,
239
struct ifnet *ifp)
240
{
241
struct ip6_hdr *ip6;
242
243
if (ifp == NULL)
244
return;
245
246
if (m->m_len < sizeof(struct ip6_hdr)) {
247
m = m_pullup(m, sizeof(struct ip6_hdr));
248
if (m == NULL) {
249
IP6STAT_INC(ip6s_exthdrtoolong);
250
return;
251
}
252
}
253
ip6 = mtod(m, struct ip6_hdr *);
254
255
if (in6_setscope(&ip6->ip6_src, ifp, NULL) != 0)
256
return;
257
if (in6_setscope(&ip6->ip6_dst, ifp, NULL) != 0)
258
return;
259
260
icmp6_error(m, type, code, param);
261
}
262
263
/*
264
* Generate an error packet of type error in response to bad IP6 packet.
265
*/
266
void
267
icmp6_error(struct mbuf *m, int type, int code, int param)
268
{
269
struct ip6_hdr *oip6, *nip6;
270
struct icmp6_hdr *icmp6;
271
struct epoch_tracker et;
272
u_int preplen;
273
int off;
274
int nxt;
275
276
ICMP6STAT_INC(icp6s_error);
277
278
/* count per-type-code statistics */
279
icmp6_errcount(type, code);
280
281
#ifdef M_DECRYPTED /*not openbsd*/
282
if (m->m_flags & M_DECRYPTED) {
283
ICMP6STAT_INC(icp6s_canterror);
284
goto freeit;
285
}
286
#endif
287
288
if (m->m_len < sizeof(struct ip6_hdr)) {
289
m = m_pullup(m, sizeof(struct ip6_hdr));
290
if (m == NULL) {
291
IP6STAT_INC(ip6s_exthdrtoolong);
292
return;
293
}
294
}
295
oip6 = mtod(m, struct ip6_hdr *);
296
297
/*
298
* If the destination address of the erroneous packet is a multicast
299
* address, or the packet was sent using link-layer multicast,
300
* we should basically suppress sending an error (RFC 2463, Section
301
* 2.4).
302
* We have two exceptions (the item e.2 in that section):
303
* - the Packet Too Big message can be sent for path MTU discovery.
304
* - the Parameter Problem Message that can be allowed an icmp6 error
305
* in the option type field. This check has been done in
306
* ip6_unknown_opt(), so we can just check the type and code.
307
*/
308
if ((m->m_flags & (M_BCAST|M_MCAST) ||
309
IN6_IS_ADDR_MULTICAST(&oip6->ip6_dst)) &&
310
(type != ICMP6_PACKET_TOO_BIG &&
311
(type != ICMP6_PARAM_PROB ||
312
code != ICMP6_PARAMPROB_OPTION)))
313
goto freeit;
314
315
/*
316
* RFC 2463, 2.4 (e.5): source address check.
317
* XXX: the case of anycast source?
318
*/
319
if (IN6_IS_ADDR_UNSPECIFIED(&oip6->ip6_src) ||
320
IN6_IS_ADDR_MULTICAST(&oip6->ip6_src))
321
goto freeit;
322
323
/*
324
* If we are about to send ICMPv6 against ICMPv6 error/redirect,
325
* don't do it.
326
*/
327
nxt = -1;
328
off = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt);
329
if (off >= 0 && nxt == IPPROTO_ICMPV6) {
330
struct icmp6_hdr *icp;
331
332
if (m->m_len < off + sizeof(struct icmp6_hdr)) {
333
m = m_pullup(m, off + sizeof(struct icmp6_hdr));
334
if (m == NULL) {
335
IP6STAT_INC(ip6s_exthdrtoolong);
336
return;
337
}
338
}
339
oip6 = mtod(m, struct ip6_hdr *);
340
icp = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
341
342
if (icp->icmp6_type < ICMP6_ECHO_REQUEST ||
343
icp->icmp6_type == ND_REDIRECT) {
344
/*
345
* ICMPv6 error
346
* Special case: for redirect (which is
347
* informational) we must not send icmp6 error.
348
*/
349
ICMP6STAT_INC(icp6s_canterror);
350
goto freeit;
351
} else {
352
/* ICMPv6 informational - send the error */
353
}
354
} else {
355
/* non-ICMPv6 - send the error */
356
}
357
358
/* Finally, do rate limitation check. */
359
if (icmp6_ratelimit(&oip6->ip6_src, type, code))
360
goto freeit;
361
362
/*
363
* OK, ICMP6 can be generated.
364
*/
365
366
if (m->m_pkthdr.len >= ICMPV6_PLD_MAXLEN)
367
m_adj(m, ICMPV6_PLD_MAXLEN - m->m_pkthdr.len);
368
369
preplen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
370
M_PREPEND(m, preplen, M_NOWAIT); /* FIB is also copied over. */
371
if (m == NULL) {
372
nd6log((LOG_DEBUG, "ENOBUFS in icmp6_error %d\n", __LINE__));
373
return;
374
}
375
376
nip6 = mtod(m, struct ip6_hdr *);
377
nip6->ip6_src = oip6->ip6_src;
378
nip6->ip6_dst = oip6->ip6_dst;
379
380
in6_clearscope(&oip6->ip6_src);
381
in6_clearscope(&oip6->ip6_dst);
382
383
icmp6 = (struct icmp6_hdr *)(nip6 + 1);
384
icmp6->icmp6_type = type;
385
icmp6->icmp6_code = code;
386
icmp6->icmp6_pptr = htonl((u_int32_t)param);
387
388
ICMP6STAT_INC2(icp6s_outhist, type);
389
NET_EPOCH_ENTER(et);
390
icmp6_reflect(m, sizeof(struct ip6_hdr)); /* header order: IPv6 - ICMPv6 */
391
NET_EPOCH_EXIT(et);
392
393
return;
394
395
freeit:
396
/*
397
* If we can't tell whether or not we can generate ICMP6, free it.
398
*/
399
m_freem(m);
400
}
401
402
int
403
icmp6_errmap(const struct icmp6_hdr *icmp6)
404
{
405
406
switch (icmp6->icmp6_type) {
407
case ICMP6_DST_UNREACH:
408
switch (icmp6->icmp6_code) {
409
case ICMP6_DST_UNREACH_NOROUTE:
410
case ICMP6_DST_UNREACH_ADDR:
411
return (EHOSTUNREACH);
412
case ICMP6_DST_UNREACH_NOPORT:
413
case ICMP6_DST_UNREACH_ADMIN:
414
return (ECONNREFUSED);
415
case ICMP6_DST_UNREACH_BEYONDSCOPE:
416
return (ENOPROTOOPT);
417
default:
418
return (0); /* Shouldn't happen. */
419
}
420
case ICMP6_PACKET_TOO_BIG:
421
return (EMSGSIZE);
422
case ICMP6_TIME_EXCEEDED:
423
switch (icmp6->icmp6_code) {
424
case ICMP6_TIME_EXCEED_TRANSIT:
425
return (EHOSTUNREACH);
426
case ICMP6_TIME_EXCEED_REASSEMBLY:
427
return (0);
428
default:
429
return (0); /* Shouldn't happen. */
430
}
431
case ICMP6_PARAM_PROB:
432
switch (icmp6->icmp6_code) {
433
case ICMP6_PARAMPROB_NEXTHEADER:
434
return (ECONNREFUSED);
435
case ICMP6_PARAMPROB_HEADER:
436
case ICMP6_PARAMPROB_OPTION:
437
return (ENOPROTOOPT);
438
default:
439
return (0); /* Shouldn't happen. */
440
}
441
default:
442
return (0);
443
}
444
}
445
446
/*
447
* Process a received ICMP6 message.
448
*/
449
int
450
icmp6_input(struct mbuf **mp, int *offp, int proto)
451
{
452
struct mbuf *m, *n;
453
struct ifnet *ifp;
454
struct ip6_hdr *ip6, *nip6;
455
struct icmp6_hdr *icmp6, *nicmp6;
456
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
457
int code, error, icmp6len, ip6len, noff, off, sum;
458
459
NET_EPOCH_ASSERT();
460
461
m = *mp;
462
off = *offp;
463
464
if (m->m_len < off + sizeof(struct icmp6_hdr)) {
465
m = m_pullup(m, off + sizeof(struct icmp6_hdr));
466
if (m == NULL) {
467
IP6STAT_INC(ip6s_exthdrtoolong);
468
*mp = m;
469
return (IPPROTO_DONE);
470
}
471
}
472
473
/*
474
* Locate icmp6 structure in mbuf, and check
475
* that not corrupted and of at least minimum length
476
*/
477
478
icmp6len = m->m_pkthdr.len - off;
479
if (icmp6len < sizeof(struct icmp6_hdr)) {
480
ICMP6STAT_INC(icp6s_tooshort);
481
goto freeit;
482
}
483
484
ip6 = mtod(m, struct ip6_hdr *);
485
ifp = m->m_pkthdr.rcvif;
486
/*
487
* Check multicast group membership.
488
* Note: SSM filters are not applied for ICMPv6 traffic.
489
*/
490
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
491
struct in6_multi *inm;
492
493
inm = in6m_lookup(ifp, &ip6->ip6_dst);
494
if (inm == NULL) {
495
IP6STAT_INC(ip6s_notmember);
496
in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
497
goto freeit;
498
}
499
}
500
501
/* Calculate the checksum. */
502
icmp6 = (struct icmp6_hdr *)((caddr_t)ip6 + off);
503
code = icmp6->icmp6_code;
504
if ((sum = in6_cksum(m, IPPROTO_ICMPV6, off, icmp6len)) != 0) {
505
nd6log((LOG_ERR,
506
"ICMP6 checksum error(%d|%x) %s\n",
507
icmp6->icmp6_type, sum,
508
ip6_sprintf(ip6bufs, &ip6->ip6_src)));
509
ICMP6STAT_INC(icp6s_checksum);
510
goto freeit;
511
}
512
513
ICMP6STAT_INC2(icp6s_inhist, icmp6->icmp6_type);
514
icmp6_ifstat_inc(ifp, ifs6_in_msg);
515
if (icmp6->icmp6_type < ICMP6_INFOMSG_MASK)
516
icmp6_ifstat_inc(ifp, ifs6_in_error);
517
518
ip6len = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen);
519
switch (icmp6->icmp6_type) {
520
case ICMP6_DST_UNREACH:
521
icmp6_ifstat_inc(ifp, ifs6_in_dstunreach);
522
switch (code) {
523
case ICMP6_DST_UNREACH_ADMIN:
524
icmp6_ifstat_inc(ifp, ifs6_in_adminprohib);
525
case ICMP6_DST_UNREACH_NOROUTE:
526
case ICMP6_DST_UNREACH_ADDR:
527
case ICMP6_DST_UNREACH_BEYONDSCOPE:
528
case ICMP6_DST_UNREACH_NOPORT:
529
goto deliver;
530
default:
531
goto badcode;
532
}
533
case ICMP6_PACKET_TOO_BIG:
534
icmp6_ifstat_inc(ifp, ifs6_in_pkttoobig);
535
/*
536
* Validation is made in icmp6_mtudisc_update.
537
* Updating the path MTU will be done after examining
538
* intermediate extension headers.
539
*/
540
goto deliver;
541
case ICMP6_TIME_EXCEEDED:
542
icmp6_ifstat_inc(ifp, ifs6_in_timeexceed);
543
switch (code) {
544
case ICMP6_TIME_EXCEED_TRANSIT:
545
case ICMP6_TIME_EXCEED_REASSEMBLY:
546
goto deliver;
547
default:
548
goto badcode;
549
}
550
case ICMP6_PARAM_PROB:
551
icmp6_ifstat_inc(ifp, ifs6_in_paramprob);
552
switch (code) {
553
case ICMP6_PARAMPROB_NEXTHEADER:
554
case ICMP6_PARAMPROB_HEADER:
555
case ICMP6_PARAMPROB_OPTION:
556
goto deliver;
557
default:
558
goto badcode;
559
}
560
case ICMP6_ECHO_REQUEST:
561
icmp6_ifstat_inc(ifp, ifs6_in_echo);
562
if (code != 0)
563
goto badcode;
564
if (icmp6_ratelimit(&ip6->ip6_src, ICMP6_ECHO_REPLY, 0))
565
break;
566
if ((n = m_copym(m, 0, M_COPYALL, M_NOWAIT)) == NULL) {
567
/* Give up remote */
568
break;
569
}
570
if (!M_WRITABLE(n)
571
|| n->m_len < off + sizeof(struct icmp6_hdr)) {
572
struct mbuf *n0 = n;
573
int n0len;
574
575
CTASSERT(sizeof(*nip6) + sizeof(*nicmp6) <= MHLEN);
576
n = m_gethdr(M_NOWAIT, n0->m_type);
577
if (n == NULL) {
578
/* Give up remote */
579
m_freem(n0);
580
break;
581
}
582
583
m_move_pkthdr(n, n0); /* FIB copied. */
584
n0len = n0->m_pkthdr.len; /* save for use below */
585
/*
586
* Copy IPv6 and ICMPv6 only.
587
*/
588
nip6 = mtod(n, struct ip6_hdr *);
589
bcopy(ip6, nip6, sizeof(struct ip6_hdr));
590
nicmp6 = (struct icmp6_hdr *)(nip6 + 1);
591
bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr));
592
noff = sizeof(struct ip6_hdr);
593
/* new mbuf contains only ipv6+icmpv6 headers */
594
n->m_len = noff + sizeof(struct icmp6_hdr);
595
/*
596
* Adjust mbuf. ip6_plen will be adjusted in
597
* ip6_output().
598
*/
599
m_adj(n0, off + sizeof(struct icmp6_hdr));
600
/* recalculate complete packet size */
601
n->m_pkthdr.len = n0len + (noff - off);
602
n->m_next = n0;
603
} else {
604
if (n->m_len < off + sizeof(*nicmp6)) {
605
n = m_pullup(n, off + sizeof(*nicmp6));
606
if (n == NULL) {
607
IP6STAT_INC(ip6s_exthdrtoolong);
608
break;
609
}
610
}
611
nicmp6 = (struct icmp6_hdr *)(mtod(n, caddr_t) + off);
612
noff = off;
613
}
614
if (n) {
615
nicmp6->icmp6_type = ICMP6_ECHO_REPLY;
616
nicmp6->icmp6_code = 0;
617
ICMP6STAT_INC(icp6s_reflect);
618
ICMP6STAT_INC2(icp6s_outhist, ICMP6_ECHO_REPLY);
619
icmp6_reflect(n, noff);
620
}
621
break;
622
623
case ICMP6_ECHO_REPLY:
624
icmp6_ifstat_inc(ifp, ifs6_in_echoreply);
625
if (code != 0)
626
goto badcode;
627
break;
628
629
case MLD_LISTENER_QUERY:
630
case MLD_LISTENER_REPORT:
631
case MLD_LISTENER_DONE:
632
case MLDV2_LISTENER_REPORT:
633
/*
634
* Drop MLD traffic which is not link-local, has a hop limit
635
* of greater than 1 hop, or which does not have the
636
* IPv6 HBH Router Alert option.
637
* As IPv6 HBH options are stripped in ip6_input() we must
638
* check an mbuf header flag.
639
* XXX Should we also sanity check that these messages
640
* were directed to a link-local multicast prefix?
641
*/
642
if ((ip6->ip6_hlim != 1) || (m->m_flags & M_RTALERT_MLD) == 0)
643
goto freeit;
644
if (mld_input(&m, off, icmp6len) != 0) {
645
*mp = NULL;
646
return (IPPROTO_DONE);
647
}
648
/* m stays. */
649
break;
650
651
case ICMP6_WRUREQUEST: /* ICMP6_FQDN_QUERY */
652
{
653
enum { WRU, FQDN } mode;
654
struct prison *pr;
655
656
if (!V_icmp6_nodeinfo)
657
break;
658
659
if (icmp6len == sizeof(struct icmp6_hdr) + 4)
660
mode = WRU;
661
else if (icmp6len >= sizeof(struct icmp6_nodeinfo))
662
mode = FQDN;
663
else
664
goto badlen;
665
666
pr = NULL;
667
sx_slock(&allprison_lock);
668
TAILQ_FOREACH(pr, &allprison, pr_list)
669
if (pr->pr_vnet == ifp->if_vnet)
670
break;
671
sx_sunlock(&allprison_lock);
672
if (pr == NULL)
673
pr = curthread->td_ucred->cr_prison;
674
if (mode == FQDN) {
675
if (m->m_len < off + sizeof(struct icmp6_nodeinfo)) {
676
m = m_pullup(m, off +
677
sizeof(struct icmp6_nodeinfo));
678
if (m == NULL) {
679
IP6STAT_INC(ip6s_exthdrtoolong);
680
*mp = m;
681
return (IPPROTO_DONE);
682
}
683
}
684
n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
685
if (n)
686
n = ni6_input(n, off, pr);
687
/* XXX meaningless if n == NULL */
688
noff = sizeof(struct ip6_hdr);
689
} else {
690
u_char *p;
691
int maxhlen, hlen;
692
693
/*
694
* XXX: this combination of flags is pointless,
695
* but should we keep this for compatibility?
696
*/
697
if ((V_icmp6_nodeinfo & (ICMP6_NODEINFO_FQDNOK |
698
ICMP6_NODEINFO_TMPADDROK)) !=
699
(ICMP6_NODEINFO_FQDNOK | ICMP6_NODEINFO_TMPADDROK))
700
break;
701
702
if (code != 0)
703
goto badcode;
704
705
CTASSERT(sizeof(*nip6) + sizeof(*nicmp6) + 4 <= MHLEN);
706
n = m_gethdr(M_NOWAIT, m->m_type);
707
if (n == NULL) {
708
/* Give up remote */
709
break;
710
}
711
if (!m_dup_pkthdr(n, m, M_NOWAIT)) {
712
/*
713
* Previous code did a blind M_COPY_PKTHDR
714
* and said "just for rcvif". If true, then
715
* we could tolerate the dup failing (due to
716
* the deep copy of the tag chain). For now
717
* be conservative and just fail.
718
*/
719
m_free(n);
720
n = NULL;
721
break;
722
}
723
/*
724
* Copy IPv6 and ICMPv6 only.
725
*/
726
nip6 = mtod(n, struct ip6_hdr *);
727
bcopy(ip6, nip6, sizeof(struct ip6_hdr));
728
nicmp6 = (struct icmp6_hdr *)(nip6 + 1);
729
bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr));
730
p = (u_char *)(nicmp6 + 1);
731
bzero(p, 4);
732
733
maxhlen = M_TRAILINGSPACE(n) -
734
(sizeof(*nip6) + sizeof(*nicmp6) + 4);
735
mtx_lock(&pr->pr_mtx);
736
hlen = strlen(pr->pr_hostname);
737
if (maxhlen > hlen)
738
maxhlen = hlen;
739
/* meaningless TTL */
740
bcopy(pr->pr_hostname, p + 4, maxhlen);
741
mtx_unlock(&pr->pr_mtx);
742
noff = sizeof(struct ip6_hdr);
743
n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) +
744
sizeof(struct icmp6_hdr) + 4 + maxhlen;
745
nicmp6->icmp6_type = ICMP6_WRUREPLY;
746
nicmp6->icmp6_code = 0;
747
}
748
if (n) {
749
ICMP6STAT_INC(icp6s_reflect);
750
ICMP6STAT_INC2(icp6s_outhist, ICMP6_WRUREPLY);
751
icmp6_reflect(n, noff);
752
}
753
break;
754
}
755
756
case ICMP6_WRUREPLY:
757
if (code != 0)
758
goto badcode;
759
break;
760
761
case ND_ROUTER_SOLICIT:
762
icmp6_ifstat_inc(ifp, ifs6_in_routersolicit);
763
if (code != 0)
764
goto badcode;
765
if (icmp6len < sizeof(struct nd_router_solicit))
766
goto badlen;
767
if (send_sendso_input_hook != NULL) {
768
if (m->m_len < off + icmp6len) {
769
m = m_pullup(m, off + icmp6len);
770
if (m == NULL) {
771
IP6STAT_INC(ip6s_exthdrtoolong);
772
*mp = NULL;
773
return (IPPROTO_DONE);
774
}
775
}
776
error = send_sendso_input_hook(m, ifp, SND_IN, ip6len);
777
if (error == 0) {
778
m = NULL;
779
goto freeit;
780
}
781
}
782
n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
783
nd6_rs_input(m, off, icmp6len);
784
m = n;
785
if (m == NULL)
786
goto freeit;
787
break;
788
789
case ND_ROUTER_ADVERT:
790
icmp6_ifstat_inc(ifp, ifs6_in_routeradvert);
791
if (code != 0)
792
goto badcode;
793
if (icmp6len < sizeof(struct nd_router_advert))
794
goto badlen;
795
if (send_sendso_input_hook != NULL) {
796
error = send_sendso_input_hook(m, ifp, SND_IN, ip6len);
797
if (error == 0) {
798
m = NULL;
799
goto freeit;
800
}
801
}
802
n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
803
nd6_ra_input(m, off, icmp6len);
804
m = n;
805
if (m == NULL)
806
goto freeit;
807
break;
808
809
case ND_NEIGHBOR_SOLICIT:
810
icmp6_ifstat_inc(ifp, ifs6_in_neighborsolicit);
811
if (code != 0)
812
goto badcode;
813
if (icmp6len < sizeof(struct nd_neighbor_solicit))
814
goto badlen;
815
if (send_sendso_input_hook != NULL) {
816
error = send_sendso_input_hook(m, ifp, SND_IN, ip6len);
817
if (error == 0) {
818
m = NULL;
819
goto freeit;
820
}
821
}
822
n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
823
nd6_ns_input(m, off, icmp6len);
824
m = n;
825
if (m == NULL)
826
goto freeit;
827
break;
828
829
case ND_NEIGHBOR_ADVERT:
830
icmp6_ifstat_inc(ifp, ifs6_in_neighboradvert);
831
if (code != 0)
832
goto badcode;
833
if (icmp6len < sizeof(struct nd_neighbor_advert))
834
goto badlen;
835
if (send_sendso_input_hook != NULL) {
836
error = send_sendso_input_hook(m, ifp, SND_IN, ip6len);
837
if (error == 0) {
838
m = NULL;
839
goto freeit;
840
}
841
}
842
n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
843
nd6_na_input(m, off, icmp6len);
844
m = n;
845
if (m == NULL)
846
goto freeit;
847
break;
848
849
case ND_REDIRECT:
850
icmp6_ifstat_inc(ifp, ifs6_in_redirect);
851
if (code != 0)
852
goto badcode;
853
if (icmp6len < sizeof(struct nd_redirect))
854
goto badlen;
855
if (send_sendso_input_hook != NULL) {
856
error = send_sendso_input_hook(m, ifp, SND_IN, ip6len);
857
if (error == 0) {
858
m = NULL;
859
goto freeit;
860
}
861
}
862
n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
863
icmp6_redirect_input(m, off);
864
m = n;
865
if (m == NULL)
866
goto freeit;
867
break;
868
869
case ICMP6_ROUTER_RENUMBERING:
870
if (code != ICMP6_ROUTER_RENUMBERING_COMMAND &&
871
code != ICMP6_ROUTER_RENUMBERING_RESULT)
872
goto badcode;
873
if (icmp6len < sizeof(struct icmp6_router_renum))
874
goto badlen;
875
break;
876
877
default:
878
nd6log((LOG_DEBUG,
879
"icmp6_input: unknown type %d(src=%s, dst=%s, ifid=%d)\n",
880
icmp6->icmp6_type, ip6_sprintf(ip6bufs, &ip6->ip6_src),
881
ip6_sprintf(ip6bufd, &ip6->ip6_dst),
882
ifp ? ifp->if_index : 0));
883
if (icmp6->icmp6_type < ICMP6_ECHO_REQUEST) {
884
/* ICMPv6 error: MUST deliver it by spec... */
885
goto deliver;
886
} else {
887
/* ICMPv6 informational: MUST not deliver */
888
break;
889
}
890
deliver:
891
if (icmp6_notify_error(&m, off, icmp6len) != 0) {
892
/* In this case, m should've been freed. */
893
*mp = NULL;
894
return (IPPROTO_DONE);
895
}
896
break;
897
898
badcode:
899
ICMP6STAT_INC(icp6s_badcode);
900
break;
901
902
badlen:
903
ICMP6STAT_INC(icp6s_badlen);
904
break;
905
}
906
907
/* deliver the packet to appropriate sockets */
908
icmp6_rip6_input(&m, *offp);
909
910
*mp = m;
911
return (IPPROTO_DONE);
912
913
freeit:
914
m_freem(m);
915
*mp = NULL;
916
return (IPPROTO_DONE);
917
}
918
919
static int
920
icmp6_notify_error(struct mbuf **mp, int off, int icmp6len)
921
{
922
struct mbuf *m;
923
struct icmp6_hdr *icmp6;
924
struct ip6_hdr *eip6;
925
u_int32_t notifymtu;
926
struct sockaddr_in6 icmp6src, icmp6dst;
927
928
m = *mp;
929
930
if (icmp6len < sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr)) {
931
ICMP6STAT_INC(icp6s_tooshort);
932
goto freeit;
933
}
934
935
if (m->m_len < off + sizeof(*icmp6) + sizeof(struct ip6_hdr)) {
936
m = m_pullup(m, off + sizeof(*icmp6) + sizeof(struct ip6_hdr));
937
if (m == NULL) {
938
IP6STAT_INC(ip6s_exthdrtoolong);
939
*mp = m;
940
return (-1);
941
}
942
}
943
icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
944
eip6 = (struct ip6_hdr *)(icmp6 + 1);
945
bzero(&icmp6dst, sizeof(icmp6dst));
946
947
/* Detect the upper level protocol */
948
{
949
u_int8_t nxt = eip6->ip6_nxt;
950
int eoff = off + sizeof(struct icmp6_hdr) +
951
sizeof(struct ip6_hdr);
952
struct ip6ctlparam ip6cp;
953
int icmp6type = icmp6->icmp6_type;
954
struct ip6_frag *fh;
955
struct ip6_rthdr *rth;
956
struct ip6_rthdr0 *rth0;
957
int rthlen;
958
959
while (1) { /* XXX: should avoid infinite loop explicitly? */
960
struct ip6_ext *eh;
961
962
switch (nxt) {
963
case IPPROTO_HOPOPTS:
964
case IPPROTO_DSTOPTS:
965
case IPPROTO_AH:
966
if (m->m_len < eoff + sizeof(struct ip6_ext)) {
967
m = m_pullup(m, eoff +
968
sizeof(struct ip6_ext));
969
if (m == NULL) {
970
IP6STAT_INC(ip6s_exthdrtoolong);
971
*mp = m;
972
return (-1);
973
}
974
}
975
eh = (struct ip6_ext *)
976
(mtod(m, caddr_t) + eoff);
977
if (nxt == IPPROTO_AH)
978
eoff += (eh->ip6e_len + 2) << 2;
979
else
980
eoff += (eh->ip6e_len + 1) << 3;
981
nxt = eh->ip6e_nxt;
982
break;
983
case IPPROTO_ROUTING:
984
/*
985
* When the erroneous packet contains a
986
* routing header, we should examine the
987
* header to determine the final destination.
988
* Otherwise, we can't properly update
989
* information that depends on the final
990
* destination (e.g. path MTU).
991
*/
992
if (m->m_len < eoff + sizeof(*rth)) {
993
m = m_pullup(m, eoff + sizeof(*rth));
994
if (m == NULL) {
995
IP6STAT_INC(ip6s_exthdrtoolong);
996
*mp = m;
997
return (-1);
998
}
999
}
1000
rth = (struct ip6_rthdr *)
1001
(mtod(m, caddr_t) + eoff);
1002
rthlen = (rth->ip6r_len + 1) << 3;
1003
/*
1004
* XXX: currently there is no
1005
* officially defined type other
1006
* than type-0.
1007
* Note that if the segment left field
1008
* is 0, all intermediate hops must
1009
* have been passed.
1010
*/
1011
if (rth->ip6r_segleft &&
1012
rth->ip6r_type == IPV6_RTHDR_TYPE_0) {
1013
int hops;
1014
1015
if (m->m_len < eoff + rthlen) {
1016
m = m_pullup(m, eoff + rthlen);
1017
if (m == NULL) {
1018
IP6STAT_INC(
1019
ip6s_exthdrtoolong);
1020
*mp = m;
1021
return (-1);
1022
}
1023
}
1024
rth0 = (struct ip6_rthdr0 *)
1025
(mtod(m, caddr_t) + eoff);
1026
1027
/* just ignore a bogus header */
1028
if ((rth0->ip6r0_len % 2) == 0 &&
1029
(hops = rth0->ip6r0_len/2))
1030
icmp6dst.sin6_addr = *((struct in6_addr *)(rth0 + 1) + (hops - 1));
1031
}
1032
eoff += rthlen;
1033
nxt = rth->ip6r_nxt;
1034
break;
1035
case IPPROTO_FRAGMENT:
1036
if (m->m_len < eoff + sizeof(struct ip6_frag)) {
1037
m = m_pullup(m, eoff +
1038
sizeof(struct ip6_frag));
1039
if (m == NULL) {
1040
IP6STAT_INC(ip6s_exthdrtoolong);
1041
*mp = m;
1042
return (-1);
1043
}
1044
}
1045
fh = (struct ip6_frag *)(mtod(m, caddr_t) +
1046
eoff);
1047
/*
1048
* Data after a fragment header is meaningless
1049
* unless it is the first fragment, but
1050
* we'll go to the notify label for path MTU
1051
* discovery.
1052
*/
1053
if (fh->ip6f_offlg & IP6F_OFF_MASK)
1054
goto notify;
1055
1056
eoff += sizeof(struct ip6_frag);
1057
nxt = fh->ip6f_nxt;
1058
break;
1059
default:
1060
/*
1061
* This case includes ESP and the No Next
1062
* Header. In such cases going to the notify
1063
* label does not have any meaning
1064
* (i.e. ctlfunc will be NULL), but we go
1065
* anyway since we might have to update
1066
* path MTU information.
1067
*/
1068
goto notify;
1069
}
1070
}
1071
notify:
1072
icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
1073
1074
/*
1075
* retrieve parameters from the inner IPv6 header, and convert
1076
* them into sockaddr structures.
1077
* XXX: there is no guarantee that the source or destination
1078
* addresses of the inner packet are in the same scope as
1079
* the addresses of the icmp packet. But there is no other
1080
* way to determine the zone.
1081
*/
1082
eip6 = (struct ip6_hdr *)(icmp6 + 1);
1083
1084
/*
1085
* Protocol layers can't do anything useful with unspecified
1086
* addresses.
1087
*/
1088
if (IN6_IS_ADDR_UNSPECIFIED(&eip6->ip6_src) ||
1089
IN6_IS_ADDR_UNSPECIFIED(&eip6->ip6_dst))
1090
goto freeit;
1091
1092
icmp6dst.sin6_len = sizeof(struct sockaddr_in6);
1093
icmp6dst.sin6_family = AF_INET6;
1094
if (IN6_IS_ADDR_UNSPECIFIED(&icmp6dst.sin6_addr))
1095
icmp6dst.sin6_addr = eip6->ip6_dst;
1096
if (in6_setscope(&icmp6dst.sin6_addr, m->m_pkthdr.rcvif, NULL))
1097
goto freeit;
1098
bzero(&icmp6src, sizeof(icmp6src));
1099
icmp6src.sin6_len = sizeof(struct sockaddr_in6);
1100
icmp6src.sin6_family = AF_INET6;
1101
icmp6src.sin6_addr = eip6->ip6_src;
1102
if (in6_setscope(&icmp6src.sin6_addr, m->m_pkthdr.rcvif, NULL))
1103
goto freeit;
1104
icmp6src.sin6_flowinfo =
1105
(eip6->ip6_flow & IPV6_FLOWLABEL_MASK);
1106
1107
ip6cp.ip6c_m = m;
1108
ip6cp.ip6c_icmp6 = icmp6;
1109
ip6cp.ip6c_ip6 = (struct ip6_hdr *)(icmp6 + 1);
1110
ip6cp.ip6c_off = eoff;
1111
ip6cp.ip6c_finaldst = &icmp6dst;
1112
ip6cp.ip6c_src = &icmp6src;
1113
ip6cp.ip6c_nxt = nxt;
1114
1115
if (icmp6type == ICMP6_PACKET_TOO_BIG) {
1116
notifymtu = ntohl(icmp6->icmp6_mtu);
1117
ip6cp.ip6c_cmdarg = (void *)&notifymtu;
1118
icmp6_mtudisc_update(&ip6cp);
1119
}
1120
1121
if (ip6_ctlprotox[nxt] != NULL)
1122
ip6_ctlprotox[nxt](&ip6cp);
1123
}
1124
*mp = m;
1125
return (0);
1126
1127
freeit:
1128
m_freem(m);
1129
*mp = NULL;
1130
return (-1);
1131
}
1132
1133
static void
1134
icmp6_mtudisc_update(struct ip6ctlparam *ip6cp)
1135
{
1136
struct in6_addr *dst = &ip6cp->ip6c_finaldst->sin6_addr;
1137
struct icmp6_hdr *icmp6 = ip6cp->ip6c_icmp6;
1138
struct mbuf *m = ip6cp->ip6c_m;
1139
u_int mtu = ntohl(icmp6->icmp6_mtu);
1140
struct in_conninfo inc;
1141
uint32_t max_mtu;
1142
1143
if (mtu < IPV6_MMTU)
1144
return;
1145
1146
bzero(&inc, sizeof(inc));
1147
inc.inc_fibnum = M_GETFIB(m);
1148
inc.inc_flags |= INC_ISIPV6;
1149
inc.inc6_faddr = *dst;
1150
if (in6_setscope(&inc.inc6_faddr, m->m_pkthdr.rcvif, NULL))
1151
return;
1152
1153
max_mtu = tcp_hc_getmtu(&inc);
1154
if (max_mtu == 0)
1155
max_mtu = tcp_maxmtu6(&inc, NULL);
1156
1157
if (mtu < max_mtu) {
1158
tcp_hc_updatemtu(&inc, mtu);
1159
ICMP6STAT_INC(icp6s_pmtuchg);
1160
}
1161
}
1162
1163
/*
1164
* Process a Node Information Query packet, based on
1165
* draft-ietf-ipngwg-icmp-name-lookups-07.
1166
*
1167
* Spec incompatibilities:
1168
* - IPv6 Subject address handling
1169
* - IPv4 Subject address handling support missing
1170
* - Proxy reply (answer even if it's not for me)
1171
* - joins NI group address at in6_ifattach() time only, does not cope
1172
* with hostname changes by sethostname(3)
1173
*/
1174
static struct mbuf *
1175
ni6_input(struct mbuf *m, int off, struct prison *pr)
1176
{
1177
struct icmp6_nodeinfo *ni6, *nni6;
1178
struct mbuf *n = NULL;
1179
u_int16_t qtype;
1180
int subjlen;
1181
int replylen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo);
1182
struct ni_reply_fqdn *fqdn;
1183
int addrs; /* for NI_QTYPE_NODEADDR */
1184
struct ifnet *ifp = NULL; /* for NI_QTYPE_NODEADDR */
1185
struct in6_addr in6_subj; /* subject address */
1186
struct ip6_hdr *ip6;
1187
int oldfqdn = 0; /* if 1, return pascal string (03 draft) */
1188
char *subj = NULL;
1189
struct in6_ifaddr *ia6 = NULL;
1190
1191
ip6 = mtod(m, struct ip6_hdr *);
1192
ni6 = (struct icmp6_nodeinfo *)(mtod(m, caddr_t) + off);
1193
1194
/*
1195
* Validate IPv6 source address.
1196
* The default configuration MUST be to refuse answering queries from
1197
* global-scope addresses according to RFC4602.
1198
* Notes:
1199
* - it's not very clear what "refuse" means; this implementation
1200
* simply drops it.
1201
* - it's not very easy to identify global-scope (unicast) addresses
1202
* since there are many prefixes for them. It should be safer
1203
* and in practice sufficient to check "all" but loopback and
1204
* link-local (note that site-local unicast was deprecated and
1205
* ULA is defined as global scope-wise)
1206
*/
1207
if ((V_icmp6_nodeinfo & ICMP6_NODEINFO_GLOBALOK) == 0 &&
1208
!IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) &&
1209
!IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src))
1210
goto bad;
1211
1212
/*
1213
* Validate IPv6 destination address.
1214
*
1215
* The Responder must discard the Query without further processing
1216
* unless it is one of the Responder's unicast or anycast addresses, or
1217
* a link-local scope multicast address which the Responder has joined.
1218
* [RFC4602, Section 5.]
1219
*/
1220
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
1221
if (!IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst))
1222
goto bad;
1223
/* else it's a link-local multicast, fine */
1224
} else { /* unicast or anycast */
1225
ia6 = in6ifa_ifwithaddr(&ip6->ip6_dst, 0 /* XXX */, false);
1226
if (ia6 == NULL)
1227
goto bad; /* XXX impossible */
1228
1229
if ((ia6->ia6_flags & IN6_IFF_TEMPORARY) &&
1230
!(V_icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK)) {
1231
nd6log((LOG_DEBUG, "ni6_input: ignore node info to "
1232
"a temporary address in %s:%d",
1233
__FILE__, __LINE__));
1234
goto bad;
1235
}
1236
}
1237
1238
/* validate query Subject field. */
1239
qtype = ntohs(ni6->ni_qtype);
1240
subjlen = m->m_pkthdr.len - off - sizeof(struct icmp6_nodeinfo);
1241
switch (qtype) {
1242
case NI_QTYPE_NOOP:
1243
case NI_QTYPE_SUPTYPES:
1244
/* 07 draft */
1245
if (ni6->ni_code == ICMP6_NI_SUBJ_FQDN && subjlen == 0)
1246
break;
1247
/* FALLTHROUGH */
1248
case NI_QTYPE_FQDN:
1249
case NI_QTYPE_NODEADDR:
1250
case NI_QTYPE_IPV4ADDR:
1251
switch (ni6->ni_code) {
1252
case ICMP6_NI_SUBJ_IPV6:
1253
#if ICMP6_NI_SUBJ_IPV6 != 0
1254
case 0:
1255
#endif
1256
/*
1257
* backward compatibility - try to accept 03 draft
1258
* format, where no Subject is present.
1259
*/
1260
if (qtype == NI_QTYPE_FQDN && ni6->ni_code == 0 &&
1261
subjlen == 0) {
1262
oldfqdn++;
1263
break;
1264
}
1265
#if ICMP6_NI_SUBJ_IPV6 != 0
1266
if (ni6->ni_code != ICMP6_NI_SUBJ_IPV6)
1267
goto bad;
1268
#endif
1269
1270
if (subjlen != sizeof(struct in6_addr))
1271
goto bad;
1272
1273
/*
1274
* Validate Subject address.
1275
*
1276
* Not sure what exactly "address belongs to the node"
1277
* means in the spec, is it just unicast, or what?
1278
*
1279
* At this moment we consider Subject address as
1280
* "belong to the node" if the Subject address equals
1281
* to the IPv6 destination address; validation for
1282
* IPv6 destination address should have done enough
1283
* check for us.
1284
*
1285
* We do not do proxy at this moment.
1286
*/
1287
m_copydata(m, off + sizeof(struct icmp6_nodeinfo),
1288
subjlen, (caddr_t)&in6_subj);
1289
if (in6_setscope(&in6_subj, m->m_pkthdr.rcvif, NULL))
1290
goto bad;
1291
1292
subj = (char *)&in6_subj;
1293
if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &in6_subj))
1294
break;
1295
1296
/*
1297
* XXX if we are to allow other cases, we should really
1298
* be careful about scope here.
1299
* basically, we should disallow queries toward IPv6
1300
* destination X with subject Y,
1301
* if scope(X) > scope(Y).
1302
* if we allow scope(X) > scope(Y), it will result in
1303
* information leakage across scope boundary.
1304
*/
1305
goto bad;
1306
1307
case ICMP6_NI_SUBJ_FQDN:
1308
/*
1309
* Validate Subject name with gethostname(3).
1310
*
1311
* The behavior may need some debate, since:
1312
* - we are not sure if the node has FQDN as
1313
* hostname (returned by gethostname(3)).
1314
* - the code does wildcard match for truncated names.
1315
* however, we are not sure if we want to perform
1316
* wildcard match, if gethostname(3) side has
1317
* truncated hostname.
1318
*/
1319
mtx_lock(&pr->pr_mtx);
1320
n = ni6_nametodns(pr->pr_hostname,
1321
strlen(pr->pr_hostname), 0);
1322
mtx_unlock(&pr->pr_mtx);
1323
if (!n || n->m_next || n->m_len == 0)
1324
goto bad;
1325
if (m->m_len < off + sizeof(struct icmp6_nodeinfo) +
1326
subjlen) {
1327
m = m_pullup(m, off +
1328
sizeof(struct icmp6_nodeinfo) + subjlen);
1329
if (m == NULL) {
1330
IP6STAT_INC(ip6s_exthdrtoolong);
1331
goto bad;
1332
}
1333
}
1334
/* ip6 possibly invalid but not used after. */
1335
ni6 = (struct icmp6_nodeinfo *)(mtod(m, caddr_t) + off);
1336
subj = (char *)(mtod(m, caddr_t) + off +
1337
sizeof(struct icmp6_nodeinfo));
1338
if (!ni6_dnsmatch(subj, subjlen, mtod(n, const char *),
1339
n->m_len)) {
1340
goto bad;
1341
}
1342
m_freem(n);
1343
n = NULL;
1344
break;
1345
1346
case ICMP6_NI_SUBJ_IPV4: /* XXX: to be implemented? */
1347
default:
1348
goto bad;
1349
}
1350
break;
1351
}
1352
1353
/* refuse based on configuration. XXX ICMP6_NI_REFUSED? */
1354
switch (qtype) {
1355
case NI_QTYPE_FQDN:
1356
if ((V_icmp6_nodeinfo & ICMP6_NODEINFO_FQDNOK) == 0)
1357
goto bad;
1358
break;
1359
case NI_QTYPE_NODEADDR:
1360
case NI_QTYPE_IPV4ADDR:
1361
if ((V_icmp6_nodeinfo & ICMP6_NODEINFO_NODEADDROK) == 0)
1362
goto bad;
1363
break;
1364
}
1365
1366
/* guess reply length */
1367
switch (qtype) {
1368
case NI_QTYPE_NOOP:
1369
break; /* no reply data */
1370
case NI_QTYPE_SUPTYPES:
1371
replylen += sizeof(u_int32_t);
1372
break;
1373
case NI_QTYPE_FQDN:
1374
/* XXX will append an mbuf */
1375
replylen += offsetof(struct ni_reply_fqdn, ni_fqdn_namelen);
1376
break;
1377
case NI_QTYPE_NODEADDR:
1378
addrs = ni6_addrs(ni6, m, &ifp, (struct in6_addr *)subj);
1379
if ((replylen += addrs * (sizeof(struct in6_addr) +
1380
sizeof(u_int32_t))) > MCLBYTES)
1381
replylen = MCLBYTES; /* XXX: will truncate pkt later */
1382
break;
1383
case NI_QTYPE_IPV4ADDR:
1384
/* unsupported - should respond with unknown Qtype? */
1385
break;
1386
default:
1387
/*
1388
* XXX: We must return a reply with the ICMP6 code
1389
* `unknown Qtype' in this case. However we regard the case
1390
* as an FQDN query for backward compatibility.
1391
* Older versions set a random value to this field,
1392
* so it rarely varies in the defined qtypes.
1393
* But the mechanism is not reliable...
1394
* maybe we should obsolete older versions.
1395
*/
1396
qtype = NI_QTYPE_FQDN;
1397
/* XXX will append an mbuf */
1398
replylen += offsetof(struct ni_reply_fqdn, ni_fqdn_namelen);
1399
oldfqdn++;
1400
break;
1401
}
1402
1403
/* Allocate an mbuf to reply. */
1404
if (replylen > MCLBYTES) {
1405
/*
1406
* XXX: should we try to allocate more? But MCLBYTES
1407
* is probably much larger than IPV6_MMTU...
1408
*/
1409
goto bad;
1410
}
1411
if (replylen > MHLEN)
1412
n = m_getcl(M_NOWAIT, m->m_type, M_PKTHDR);
1413
else
1414
n = m_gethdr(M_NOWAIT, m->m_type);
1415
if (n == NULL) {
1416
m_freem(m);
1417
return (NULL);
1418
}
1419
m_move_pkthdr(n, m); /* just for recvif and FIB */
1420
n->m_pkthdr.len = n->m_len = replylen;
1421
1422
/* copy mbuf header and IPv6 + Node Information base headers */
1423
bcopy(mtod(m, caddr_t), mtod(n, caddr_t), sizeof(struct ip6_hdr));
1424
nni6 = (struct icmp6_nodeinfo *)(mtod(n, struct ip6_hdr *) + 1);
1425
bcopy((caddr_t)ni6, (caddr_t)nni6, sizeof(struct icmp6_nodeinfo));
1426
1427
/* qtype dependent procedure */
1428
switch (qtype) {
1429
case NI_QTYPE_NOOP:
1430
nni6->ni_code = ICMP6_NI_SUCCESS;
1431
nni6->ni_flags = 0;
1432
break;
1433
case NI_QTYPE_SUPTYPES:
1434
{
1435
u_int32_t v;
1436
nni6->ni_code = ICMP6_NI_SUCCESS;
1437
nni6->ni_flags = htons(0x0000); /* raw bitmap */
1438
/* supports NOOP, SUPTYPES, FQDN, and NODEADDR */
1439
v = (u_int32_t)htonl(0x0000000f);
1440
bcopy(&v, nni6 + 1, sizeof(u_int32_t));
1441
break;
1442
}
1443
case NI_QTYPE_FQDN:
1444
nni6->ni_code = ICMP6_NI_SUCCESS;
1445
fqdn = (struct ni_reply_fqdn *)(mtod(n, caddr_t) +
1446
sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo));
1447
nni6->ni_flags = 0; /* XXX: meaningless TTL */
1448
fqdn->ni_fqdn_ttl = 0; /* ditto. */
1449
/*
1450
* XXX do we really have FQDN in hostname?
1451
*/
1452
mtx_lock(&pr->pr_mtx);
1453
n->m_next = ni6_nametodns(pr->pr_hostname,
1454
strlen(pr->pr_hostname), oldfqdn);
1455
mtx_unlock(&pr->pr_mtx);
1456
if (n->m_next == NULL)
1457
goto bad;
1458
/* XXX we assume that n->m_next is not a chain */
1459
if (n->m_next->m_next != NULL)
1460
goto bad;
1461
n->m_pkthdr.len += n->m_next->m_len;
1462
break;
1463
case NI_QTYPE_NODEADDR:
1464
{
1465
int lenlim, copied;
1466
1467
nni6->ni_code = ICMP6_NI_SUCCESS;
1468
n->m_pkthdr.len = n->m_len =
1469
sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo);
1470
lenlim = M_TRAILINGSPACE(n);
1471
copied = ni6_store_addrs(ni6, nni6, ifp, lenlim);
1472
/* XXX: reset mbuf length */
1473
n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) +
1474
sizeof(struct icmp6_nodeinfo) + copied;
1475
break;
1476
}
1477
default:
1478
break; /* XXX impossible! */
1479
}
1480
1481
nni6->ni_type = ICMP6_NI_REPLY;
1482
m_freem(m);
1483
return (n);
1484
1485
bad:
1486
m_freem(m);
1487
if (n)
1488
m_freem(n);
1489
return (NULL);
1490
}
1491
1492
/*
1493
* make a mbuf with DNS-encoded string. no compression support.
1494
*
1495
* XXX names with less than 2 dots (like "foo" or "foo.section") will be
1496
* treated as truncated name (two \0 at the end). this is a wild guess.
1497
*
1498
* old - return pascal string if non-zero
1499
*/
1500
static struct mbuf *
1501
ni6_nametodns(const char *name, int namelen, int old)
1502
{
1503
struct mbuf *m;
1504
char *cp, *ep;
1505
const char *p, *q;
1506
int i, len, nterm;
1507
1508
if (old)
1509
len = namelen + 1;
1510
else
1511
len = MCLBYTES;
1512
1513
/* Because MAXHOSTNAMELEN is usually 256, we use cluster mbuf. */
1514
if (len > MLEN)
1515
m = m_getcl(M_NOWAIT, MT_DATA, 0);
1516
else
1517
m = m_get(M_NOWAIT, MT_DATA);
1518
if (m == NULL)
1519
goto fail;
1520
1521
if (old) {
1522
m->m_len = len;
1523
*mtod(m, char *) = namelen;
1524
bcopy(name, mtod(m, char *) + 1, namelen);
1525
return m;
1526
} else {
1527
m->m_len = 0;
1528
cp = mtod(m, char *);
1529
ep = mtod(m, char *) + M_TRAILINGSPACE(m);
1530
1531
/* if not certain about my name, return empty buffer */
1532
if (namelen == 0)
1533
return m;
1534
1535
/*
1536
* guess if it looks like shortened hostname, or FQDN.
1537
* shortened hostname needs two trailing "\0".
1538
*/
1539
i = 0;
1540
for (p = name; p < name + namelen; p++) {
1541
if (*p && *p == '.')
1542
i++;
1543
}
1544
if (i < 2)
1545
nterm = 2;
1546
else
1547
nterm = 1;
1548
1549
p = name;
1550
while (cp < ep && p < name + namelen) {
1551
i = 0;
1552
for (q = p; q < name + namelen && *q && *q != '.'; q++)
1553
i++;
1554
/* result does not fit into mbuf */
1555
if (cp + i + 1 >= ep)
1556
goto fail;
1557
/*
1558
* DNS label length restriction, RFC1035 page 8.
1559
* "i == 0" case is included here to avoid returning
1560
* 0-length label on "foo..bar".
1561
*/
1562
if (i <= 0 || i >= 64)
1563
goto fail;
1564
*cp++ = i;
1565
bcopy(p, cp, i);
1566
cp += i;
1567
p = q;
1568
if (p < name + namelen && *p == '.')
1569
p++;
1570
}
1571
/* termination */
1572
if (cp + nterm >= ep)
1573
goto fail;
1574
while (nterm-- > 0)
1575
*cp++ = '\0';
1576
m->m_len = cp - mtod(m, char *);
1577
return m;
1578
}
1579
1580
panic("should not reach here");
1581
/* NOTREACHED */
1582
1583
fail:
1584
if (m)
1585
m_freem(m);
1586
return NULL;
1587
}
1588
1589
/*
1590
* check if two DNS-encoded string matches. takes care of truncated
1591
* form (with \0\0 at the end). no compression support.
1592
* XXX upper/lowercase match (see RFC2065)
1593
*/
1594
static int
1595
ni6_dnsmatch(const char *a, int alen, const char *b, int blen)
1596
{
1597
const char *a0, *b0;
1598
int l;
1599
1600
/* simplest case - need validation? */
1601
if (alen == blen && bcmp(a, b, alen) == 0)
1602
return 1;
1603
1604
a0 = a;
1605
b0 = b;
1606
1607
/* termination is mandatory */
1608
if (alen < 2 || blen < 2)
1609
return 0;
1610
if (a0[alen - 1] != '\0' || b0[blen - 1] != '\0')
1611
return 0;
1612
alen--;
1613
blen--;
1614
1615
while (a - a0 < alen && b - b0 < blen) {
1616
if (a - a0 + 1 > alen || b - b0 + 1 > blen)
1617
return 0;
1618
1619
if ((signed char)a[0] < 0 || (signed char)b[0] < 0)
1620
return 0;
1621
/* we don't support compression yet */
1622
if (a[0] >= 64 || b[0] >= 64)
1623
return 0;
1624
1625
/* truncated case */
1626
if (a[0] == 0 && a - a0 == alen - 1)
1627
return 1;
1628
if (b[0] == 0 && b - b0 == blen - 1)
1629
return 1;
1630
if (a[0] == 0 || b[0] == 0)
1631
return 0;
1632
1633
if (a[0] != b[0])
1634
return 0;
1635
l = a[0];
1636
if (a - a0 + 1 + l > alen || b - b0 + 1 + l > blen)
1637
return 0;
1638
if (bcmp(a + 1, b + 1, l) != 0)
1639
return 0;
1640
1641
a += 1 + l;
1642
b += 1 + l;
1643
}
1644
1645
if (a - a0 == alen && b - b0 == blen)
1646
return 1;
1647
else
1648
return 0;
1649
}
1650
1651
/*
1652
* calculate the number of addresses to be returned in the node info reply.
1653
*/
1654
static int
1655
ni6_addrs(struct icmp6_nodeinfo *ni6, struct mbuf *m, struct ifnet **ifpp,
1656
struct in6_addr *subj)
1657
{
1658
struct ifnet *ifp;
1659
struct in6_ifaddr *ifa6;
1660
struct ifaddr *ifa;
1661
int addrs = 0, addrsofif, iffound = 0;
1662
int niflags = ni6->ni_flags;
1663
1664
NET_EPOCH_ASSERT();
1665
1666
if ((niflags & NI_NODEADDR_FLAG_ALL) == 0) {
1667
switch (ni6->ni_code) {
1668
case ICMP6_NI_SUBJ_IPV6:
1669
if (subj == NULL) /* must be impossible... */
1670
return (0);
1671
break;
1672
default:
1673
/*
1674
* XXX: we only support IPv6 subject address for
1675
* this Qtype.
1676
*/
1677
return (0);
1678
}
1679
}
1680
1681
CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
1682
addrsofif = 0;
1683
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1684
if (ifa->ifa_addr->sa_family != AF_INET6)
1685
continue;
1686
ifa6 = (struct in6_ifaddr *)ifa;
1687
1688
if ((niflags & NI_NODEADDR_FLAG_ALL) == 0 &&
1689
IN6_ARE_ADDR_EQUAL(subj, &ifa6->ia_addr.sin6_addr))
1690
iffound = 1;
1691
1692
/*
1693
* IPv4-mapped addresses can only be returned by a
1694
* Node Information proxy, since they represent
1695
* addresses of IPv4-only nodes, which perforce do
1696
* not implement this protocol.
1697
* [icmp-name-lookups-07, Section 5.4]
1698
* So we don't support NI_NODEADDR_FLAG_COMPAT in
1699
* this function at this moment.
1700
*/
1701
1702
/* What do we have to do about ::1? */
1703
switch (in6_addrscope(&ifa6->ia_addr.sin6_addr)) {
1704
case IPV6_ADDR_SCOPE_LINKLOCAL:
1705
if ((niflags & NI_NODEADDR_FLAG_LINKLOCAL) == 0)
1706
continue;
1707
break;
1708
case IPV6_ADDR_SCOPE_SITELOCAL:
1709
if ((niflags & NI_NODEADDR_FLAG_SITELOCAL) == 0)
1710
continue;
1711
break;
1712
case IPV6_ADDR_SCOPE_GLOBAL:
1713
if ((niflags & NI_NODEADDR_FLAG_GLOBAL) == 0)
1714
continue;
1715
break;
1716
default:
1717
continue;
1718
}
1719
1720
/*
1721
* check if anycast is okay.
1722
* XXX: just experimental. not in the spec.
1723
*/
1724
if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0 &&
1725
(niflags & NI_NODEADDR_FLAG_ANYCAST) == 0)
1726
continue; /* we need only unicast addresses */
1727
if ((ifa6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
1728
(V_icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK) == 0) {
1729
continue;
1730
}
1731
addrsofif++; /* count the address */
1732
}
1733
if (iffound) {
1734
*ifpp = ifp;
1735
return (addrsofif);
1736
}
1737
1738
addrs += addrsofif;
1739
}
1740
1741
return (addrs);
1742
}
1743
1744
static int
1745
ni6_store_addrs(struct icmp6_nodeinfo *ni6, struct icmp6_nodeinfo *nni6,
1746
struct ifnet *ifp0, int resid)
1747
{
1748
struct ifnet *ifp;
1749
struct in6_ifaddr *ifa6;
1750
struct ifaddr *ifa;
1751
struct ifnet *ifp_dep = NULL;
1752
int copied = 0, allow_deprecated = 0;
1753
u_char *cp = (u_char *)(nni6 + 1);
1754
int niflags = ni6->ni_flags;
1755
u_int32_t ltime;
1756
1757
NET_EPOCH_ASSERT();
1758
1759
if (ifp0 == NULL && !(niflags & NI_NODEADDR_FLAG_ALL))
1760
return (0); /* needless to copy */
1761
1762
ifp = ifp0 ? ifp0 : CK_STAILQ_FIRST(&V_ifnet);
1763
again:
1764
1765
for (; ifp; ifp = CK_STAILQ_NEXT(ifp, if_link)) {
1766
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1767
if (ifa->ifa_addr->sa_family != AF_INET6)
1768
continue;
1769
ifa6 = (struct in6_ifaddr *)ifa;
1770
1771
if ((ifa6->ia6_flags & IN6_IFF_DEPRECATED) != 0 &&
1772
allow_deprecated == 0) {
1773
/*
1774
* prefererred address should be put before
1775
* deprecated addresses.
1776
*/
1777
1778
/* record the interface for later search */
1779
if (ifp_dep == NULL)
1780
ifp_dep = ifp;
1781
1782
continue;
1783
} else if ((ifa6->ia6_flags & IN6_IFF_DEPRECATED) == 0 &&
1784
allow_deprecated != 0)
1785
continue; /* we now collect deprecated addrs */
1786
1787
/* What do we have to do about ::1? */
1788
switch (in6_addrscope(&ifa6->ia_addr.sin6_addr)) {
1789
case IPV6_ADDR_SCOPE_LINKLOCAL:
1790
if ((niflags & NI_NODEADDR_FLAG_LINKLOCAL) == 0)
1791
continue;
1792
break;
1793
case IPV6_ADDR_SCOPE_SITELOCAL:
1794
if ((niflags & NI_NODEADDR_FLAG_SITELOCAL) == 0)
1795
continue;
1796
break;
1797
case IPV6_ADDR_SCOPE_GLOBAL:
1798
if ((niflags & NI_NODEADDR_FLAG_GLOBAL) == 0)
1799
continue;
1800
break;
1801
default:
1802
continue;
1803
}
1804
1805
/*
1806
* check if anycast is okay.
1807
* XXX: just experimental. not in the spec.
1808
*/
1809
if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0 &&
1810
(niflags & NI_NODEADDR_FLAG_ANYCAST) == 0)
1811
continue;
1812
if ((ifa6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
1813
(V_icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK) == 0) {
1814
continue;
1815
}
1816
1817
/* now we can copy the address */
1818
if (resid < sizeof(struct in6_addr) +
1819
sizeof(u_int32_t)) {
1820
/*
1821
* We give up much more copy.
1822
* Set the truncate flag and return.
1823
*/
1824
nni6->ni_flags |= NI_NODEADDR_FLAG_TRUNCATE;
1825
return (copied);
1826
}
1827
1828
/*
1829
* Set the TTL of the address.
1830
* The TTL value should be one of the following
1831
* according to the specification:
1832
*
1833
* 1. The remaining lifetime of a DHCP lease on the
1834
* address, or
1835
* 2. The remaining Valid Lifetime of a prefix from
1836
* which the address was derived through Stateless
1837
* Autoconfiguration.
1838
*
1839
* Note that we currently do not support stateful
1840
* address configuration by DHCPv6, so the former
1841
* case can't happen.
1842
*/
1843
if (ifa6->ia6_lifetime.ia6t_expire == 0)
1844
ltime = ND6_INFINITE_LIFETIME;
1845
else {
1846
if (ifa6->ia6_lifetime.ia6t_expire >
1847
time_uptime)
1848
ltime = htonl(ifa6->ia6_lifetime.ia6t_expire - time_uptime);
1849
else
1850
ltime = 0;
1851
}
1852
1853
bcopy(&ltime, cp, sizeof(u_int32_t));
1854
cp += sizeof(u_int32_t);
1855
1856
/* copy the address itself */
1857
bcopy(&ifa6->ia_addr.sin6_addr, cp,
1858
sizeof(struct in6_addr));
1859
in6_clearscope((struct in6_addr *)cp); /* XXX */
1860
cp += sizeof(struct in6_addr);
1861
1862
resid -= (sizeof(struct in6_addr) + sizeof(u_int32_t));
1863
copied += (sizeof(struct in6_addr) + sizeof(u_int32_t));
1864
}
1865
if (ifp0) /* we need search only on the specified IF */
1866
break;
1867
}
1868
1869
if (allow_deprecated == 0 && ifp_dep != NULL) {
1870
ifp = ifp_dep;
1871
allow_deprecated = 1;
1872
1873
goto again;
1874
}
1875
1876
return (copied);
1877
}
1878
1879
static bool
1880
icmp6_rip6_match(const struct inpcb *inp, void *v)
1881
{
1882
struct ip6_hdr *ip6 = v;
1883
1884
if ((inp->inp_vflag & INP_IPV6) == 0)
1885
return (false);
1886
if (inp->inp_ip_p != IPPROTO_ICMPV6)
1887
return (false);
1888
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) &&
1889
!IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, &ip6->ip6_dst))
1890
return (false);
1891
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) &&
1892
!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, &ip6->ip6_src))
1893
return (false);
1894
return (true);
1895
}
1896
1897
/*
1898
* XXX almost dup'ed code with rip6_input.
1899
*/
1900
static int
1901
icmp6_rip6_input(struct mbuf **mp, int off)
1902
{
1903
struct mbuf *n, *m = *mp;
1904
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1905
struct inpcb_iterator inpi = INP_ITERATOR(&V_ripcbinfo,
1906
INPLOOKUP_RLOCKPCB, icmp6_rip6_match, ip6);
1907
struct inpcb *inp;
1908
struct sockaddr_in6 fromsa;
1909
struct icmp6_hdr *icmp6;
1910
struct mbuf *opts = NULL;
1911
int delivered = 0, fib;
1912
1913
/* This is assumed to be safe; icmp6_input() does a pullup. */
1914
icmp6 = (struct icmp6_hdr *)((caddr_t)ip6 + off);
1915
1916
/*
1917
* XXX: the address may have embedded scope zone ID, which should be
1918
* hidden from applications.
1919
*/
1920
bzero(&fromsa, sizeof(fromsa));
1921
fromsa.sin6_family = AF_INET6;
1922
fromsa.sin6_len = sizeof(struct sockaddr_in6);
1923
fromsa.sin6_addr = ip6->ip6_src;
1924
if (sa6_recoverscope(&fromsa)) {
1925
m_freem(m);
1926
*mp = NULL;
1927
return (IPPROTO_DONE);
1928
}
1929
1930
fib = M_GETFIB(m);
1931
1932
while ((inp = inp_next(&inpi)) != NULL) {
1933
if (V_rip_bind_all_fibs == 0 && fib != inp->inp_inc.inc_fibnum)
1934
/*
1935
* Sockets bound to a specific FIB can only receive
1936
* packets from that FIB.
1937
*/
1938
continue;
1939
if (ICMP6_FILTER_WILLBLOCK(icmp6->icmp6_type,
1940
inp->in6p_icmp6filt))
1941
continue;
1942
/*
1943
* Recent network drivers tend to allocate a single
1944
* mbuf cluster, rather than to make a couple of
1945
* mbufs without clusters. Also, since the IPv6 code
1946
* path tries to avoid m_pullup(), it is highly
1947
* probable that we still have an mbuf cluster here
1948
* even though the necessary length can be stored in an
1949
* mbuf's internal buffer.
1950
* Meanwhile, the default size of the receive socket
1951
* buffer for raw sockets is not so large. This means
1952
* the possibility of packet loss is relatively higher
1953
* than before. To avoid this scenario, we copy the
1954
* received data to a separate mbuf that does not use
1955
* a cluster, if possible.
1956
* XXX: it is better to copy the data after stripping
1957
* intermediate headers.
1958
*/
1959
if ((m->m_flags & M_EXT) && m->m_next == NULL &&
1960
m->m_len <= MHLEN) {
1961
n = m_get(M_NOWAIT, m->m_type);
1962
if (n != NULL) {
1963
if (m_dup_pkthdr(n, m, M_NOWAIT)) {
1964
bcopy(m->m_data, n->m_data, m->m_len);
1965
n->m_len = m->m_len;
1966
} else {
1967
m_free(n);
1968
n = NULL;
1969
}
1970
}
1971
} else
1972
n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
1973
if (n == NULL)
1974
continue;
1975
if (inp->inp_flags & INP_CONTROLOPTS)
1976
ip6_savecontrol(inp, n, &opts);
1977
/* strip intermediate headers */
1978
m_adj(n, off);
1979
SOCKBUF_LOCK(&inp->inp_socket->so_rcv);
1980
if (sbappendaddr_locked(&inp->inp_socket->so_rcv,
1981
(struct sockaddr *)&fromsa, n, opts) == 0) {
1982
soroverflow_locked(inp->inp_socket);
1983
m_freem(n);
1984
if (opts)
1985
m_freem(opts);
1986
} else {
1987
sorwakeup_locked(inp->inp_socket);
1988
delivered++;
1989
}
1990
opts = NULL;
1991
}
1992
m_freem(m);
1993
*mp = NULL;
1994
if (delivered == 0)
1995
IP6STAT_DEC(ip6s_delivered);
1996
return (IPPROTO_DONE);
1997
}
1998
1999
/*
2000
* Reflect the ip6 packet back to the source.
2001
* OFF points to the icmp6 header, counted from the top of the mbuf.
2002
*/
2003
static void
2004
icmp6_reflect(struct mbuf *m, size_t off)
2005
{
2006
struct in6_addr src6, *srcp;
2007
struct ip6_hdr *ip6;
2008
struct icmp6_hdr *icmp6;
2009
struct in6_ifaddr *ia = NULL;
2010
struct ifnet *outif = NULL;
2011
int plen;
2012
int type, code, hlim;
2013
2014
/* too short to reflect */
2015
if (off < sizeof(struct ip6_hdr)) {
2016
nd6log((LOG_DEBUG,
2017
"sanity fail: off=%lx, sizeof(ip6)=%lx in %s:%d\n",
2018
(u_long)off, (u_long)sizeof(struct ip6_hdr),
2019
__FILE__, __LINE__));
2020
goto bad;
2021
}
2022
2023
/*
2024
* If there are extra headers between IPv6 and ICMPv6, strip
2025
* off that header first.
2026
*/
2027
#ifdef DIAGNOSTIC
2028
if (sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) > MHLEN)
2029
panic("assumption failed in icmp6_reflect");
2030
#endif
2031
if (off > sizeof(struct ip6_hdr)) {
2032
size_t l;
2033
struct ip6_hdr nip6;
2034
2035
l = off - sizeof(struct ip6_hdr);
2036
m_copydata(m, 0, sizeof(nip6), (caddr_t)&nip6);
2037
m_adj(m, l);
2038
l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
2039
if (m->m_len < l) {
2040
if ((m = m_pullup(m, l)) == NULL)
2041
return;
2042
}
2043
bcopy((caddr_t)&nip6, mtod(m, caddr_t), sizeof(nip6));
2044
} else /* off == sizeof(struct ip6_hdr) */ {
2045
size_t l;
2046
l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
2047
if (m->m_len < l) {
2048
if ((m = m_pullup(m, l)) == NULL)
2049
return;
2050
}
2051
}
2052
plen = m->m_pkthdr.len - sizeof(struct ip6_hdr);
2053
ip6 = mtod(m, struct ip6_hdr *);
2054
ip6->ip6_nxt = IPPROTO_ICMPV6;
2055
icmp6 = (struct icmp6_hdr *)(ip6 + 1);
2056
type = icmp6->icmp6_type; /* keep type for statistics */
2057
code = icmp6->icmp6_code; /* ditto. */
2058
hlim = 0;
2059
srcp = NULL;
2060
2061
if (__predict_false(IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src))) {
2062
nd6log((LOG_DEBUG,
2063
"icmp6_reflect: source address is unspecified\n"));
2064
goto bad;
2065
}
2066
2067
/*
2068
* If the incoming packet was addressed directly to us (i.e. unicast),
2069
* use dst as the src for the reply.
2070
* The IN6_IFF_NOTREADY case should be VERY rare, but is possible
2071
* (for example) when we encounter an error while forwarding procedure
2072
* destined to a duplicated address of ours.
2073
*/
2074
if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
2075
ia = in6ifa_ifwithaddr(&ip6->ip6_dst, 0 /* XXX */, false);
2076
if (ia != NULL && !(ia->ia6_flags &
2077
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY))) {
2078
src6 = ia->ia_addr.sin6_addr;
2079
srcp = &src6;
2080
2081
if (m->m_pkthdr.rcvif != NULL) {
2082
/* XXX: This may not be the outgoing interface */
2083
hlim =
2084
m->m_pkthdr.rcvif->if_inet6->nd_curhoplimit;
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