Bug Summary

File:netinet6/ip6_mroute.c
Warning:line 1179, column 3
Value stored to 'error' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ip6_mroute.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/netinet6/ip6_mroute.c
1/* $OpenBSD: ip6_mroute.c,v 1.127 2021/12/15 17:21:08 deraadt Exp $ */
2/* $NetBSD: ip6_mroute.c,v 1.59 2003/12/10 09:28:38 itojun Exp $ */
3/* $KAME: ip6_mroute.c,v 1.45 2001/03/25 08:38:51 itojun Exp $ */
4
5/*
6 * Copyright (C) 1998 WIDE Project.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34/* BSDI ip_mroute.c,v 2.10 1996/11/14 00:29:52 jch Exp */
35
36/*
37 * Copyright (c) 1989 Stephen Deering
38 * Copyright (c) 1992, 1993
39 * The Regents of the University of California. All rights reserved.
40 *
41 * This code is derived from software contributed to Berkeley by
42 * Stephen Deering of Stanford University.
43 *
44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions
46 * are met:
47 * 1. Redistributions of source code must retain the above copyright
48 * notice, this list of conditions and the following disclaimer.
49 * 2. Redistributions in binary form must reproduce the above copyright
50 * notice, this list of conditions and the following disclaimer in the
51 * documentation and/or other materials provided with the distribution.
52 * 3. Neither the name of the University nor the names of its contributors
53 * may be used to endorse or promote products derived from this software
54 * without specific prior written permission.
55 *
56 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
57 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
60 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66 * SUCH DAMAGE.
67 *
68 * @(#)ip_mroute.c 8.2 (Berkeley) 11/15/93
69 */
70
71/*
72 * IP multicast forwarding procedures
73 *
74 * Written by David Waitzman, BBN Labs, August 1988.
75 * Modified by Steve Deering, Stanford, February 1989.
76 * Modified by Mark J. Steiglitz, Stanford, May, 1991
77 * Modified by Van Jacobson, LBL, January 1993
78 * Modified by Ajit Thyagarajan, PARC, August 1993
79 * Modified by Bill Fenner, PARC, April 1994
80 *
81 * MROUTING Revision: 3.5.1.2
82 */
83
84#include <sys/param.h>
85#include <sys/malloc.h>
86#include <sys/systm.h>
87#include <sys/timeout.h>
88#include <sys/mbuf.h>
89#include <sys/socket.h>
90#include <sys/socketvar.h>
91#include <sys/protosw.h>
92#include <sys/kernel.h>
93#include <sys/ioctl.h>
94#include <sys/syslog.h>
95#include <sys/sysctl.h>
96
97#include <net/if.h>
98#include <net/if_var.h>
99#include <net/route.h>
100
101#include <netinet/in.h>
102#include <netinet6/in6_var.h>
103#include <netinet/ip.h>
104#include <netinet/ip6.h>
105#include <netinet/icmp6.h>
106#include <netinet6/ip6_var.h>
107#include <netinet6/ip6_mroute.h>
108#include <netinet/in_pcb.h>
109
110/* #define MCAST_DEBUG */
111
112#ifdef MCAST_DEBUG
113int mcast6_debug = 1;
114#define DPRINTF(fmt, args...)do { } while (0) \
115 do { \
116 if (mcast6_debug) \
117 printf("%s:%d " fmt "\n", \
118 __func__, __LINE__118, ## args); \
119 } while (0)
120#else
121#define DPRINTF(fmt, args...)do { } while (0) \
122 do { } while (0)
123#endif
124
125int ip6_mdq(struct mbuf *, struct ifnet *, struct rtentry *);
126void phyint_send6(struct ifnet *, struct ip6_hdr *, struct mbuf *);
127
128/*
129 * Globals. All but ip6_mrouter, ip6_mrtproto and mrt6stat could be static,
130 * except for netstat or debugging purposes.
131 */
132struct socket *ip6_mrouter[RT_TABLEID_MAX255 + 1];
133struct rttimer_queue *mrouter6q[RT_TABLEID_MAX255 + 1];
134int ip6_mrouter_ver = 0;
135int ip6_mrtproto; /* for netstat only */
136struct mrt6stat mrt6stat;
137
138#define NO_RTE_FOUND0x1 0x1
139#define RTE_FOUND0x2 0x2
140
141#define MCAST_EXPIRE_TIMEOUT30 30 /* seconds */
142
143/*
144 * Macros to compute elapsed time efficiently
145 * Borrowed from Van Jacobson's scheduling code
146 */
147#define TV_DELTA(a, b, delta)do { int xxs; delta = (a).tv_usec - (b).tv_usec; if ((xxs = (
a).tv_sec - (b).tv_sec)) { switch (xxs) { case 2: delta += 1000000
; case 1: delta += 1000000; break; default: delta += (1000000
* xxs); } } } while (0)
do { \
148 int xxs; \
149 \
150 delta = (a).tv_usec - (b).tv_usec; \
151 if ((xxs = (a).tv_sec - (b).tv_sec)) { \
152 switch (xxs) { \
153 case 2: \
154 delta += 1000000; \
155 /* FALLTHROUGH */ \
156 case 1: \
157 delta += 1000000; \
158 break; \
159 default: \
160 delta += (1000000 * xxs); \
161 } \
162 } \
163} while (0)
164
165#define TV_LT(a, b)(((a).tv_usec < (b).tv_usec && (a).tv_sec <= (b
).tv_sec) || (a).tv_sec < (b).tv_sec)
(((a).tv_usec < (b).tv_usec && \
166 (a).tv_sec <= (b).tv_sec) || (a).tv_sec < (b).tv_sec)
167
168int get_sg6_cnt(struct sioc_sg_req6 *, unsigned int);
169int get_mif6_cnt(struct sioc_mif_req6 *, unsigned int);
170int ip6_mrouter_init(struct socket *, int, int);
171int add_m6if(struct socket *, struct mif6ctl *);
172int del_m6if(struct socket *, mifi_t *);
173int add_m6fc(struct socket *, struct mf6cctl *);
174int del_m6fc(struct socket *, struct mf6cctl *);
175struct ifnet *mrt6_iflookupbymif(mifi_t, unsigned int);
176struct rtentry *mf6c_find(struct ifnet *, struct in6_addr *,
177 struct in6_addr *, unsigned int);
178struct rtentry *mrt6_mcast_add(struct ifnet *, struct sockaddr *,
179 struct sockaddr *);
180void mrt6_mcast_del(struct rtentry *, unsigned int);
181void mf6c_expire_route(struct rtentry *, struct rttimer *);
182
183/*
184 * Handle MRT setsockopt commands to modify the multicast routing tables.
185 */
186int
187ip6_mrouter_set(int cmd, struct socket *so, struct mbuf *m)
188{
189 struct inpcb *inp = sotoinpcb(so)((struct inpcb *)(so)->so_pcb);
190
191 if (cmd != MRT6_INIT108 && so != ip6_mrouter[inp->inp_rtableid])
192 return (EPERM1);
193
194 switch (cmd) {
195 case MRT6_INIT108:
196 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len < sizeof(int))
197 return (EINVAL22);
198 return (ip6_mrouter_init(so, *mtod(m, int *)((int *)((m)->m_hdr.mh_data)), cmd));
199 case MRT6_DONE101:
200 return (ip6_mrouter_done(so));
201 case MRT6_ADD_MIF102:
202 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len < sizeof(struct mif6ctl))
203 return (EINVAL22);
204 return (add_m6if(so, mtod(m, struct mif6ctl *)((struct mif6ctl *)((m)->m_hdr.mh_data))));
205 case MRT6_DEL_MIF103:
206 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len < sizeof(mifi_t))
207 return (EINVAL22);
208 return (del_m6if(so, mtod(m, mifi_t *)((mifi_t *)((m)->m_hdr.mh_data))));
209 case MRT6_ADD_MFC104:
210 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len < sizeof(struct mf6cctl))
211 return (EINVAL22);
212 return (add_m6fc(so, mtod(m, struct mf6cctl *)((struct mf6cctl *)((m)->m_hdr.mh_data))));
213 case MRT6_DEL_MFC105:
214 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len < sizeof(struct mf6cctl))
215 return (EINVAL22);
216 return (del_m6fc(so, mtod(m, struct mf6cctl *)((struct mf6cctl *)((m)->m_hdr.mh_data))));
217 default:
218 return (EOPNOTSUPP45);
219 }
220}
221
222/*
223 * Handle MRT getsockopt commands
224 */
225int
226ip6_mrouter_get(int cmd, struct socket *so, struct mbuf *m)
227{
228 struct inpcb *inp = sotoinpcb(so)((struct inpcb *)(so)->so_pcb);
229
230 if (so != ip6_mrouter[inp->inp_rtableid])
231 return (EPERM1);
232
233 switch (cmd) {
234 default:
235 return EOPNOTSUPP45;
236 }
237}
238
239/*
240 * Handle ioctl commands to obtain information from the cache
241 */
242int
243mrt6_ioctl(struct socket *so, u_long cmd, caddr_t data)
244{
245 struct inpcb *inp = sotoinpcb(so)((struct inpcb *)(so)->so_pcb);
246 int error;
247
248 if (inp == NULL((void *)0))
249 return (ENOTCONN57);
250
251 switch (cmd) {
252 case SIOCGETSGCNT_IN6(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct sioc_sg_req6) & 0x1fff) << 16) | ((('u')) <<
8) | ((106)))
:
253 NET_RLOCK_IN_IOCTL()do { rw_enter_read(&netlock); } while (0);
254 error = get_sg6_cnt((struct sioc_sg_req6 *)data,
255 inp->inp_rtableid);
256 NET_RUNLOCK_IN_IOCTL()do { rw_exit_read(&netlock); } while (0);
257 break;
258 case SIOCGETMIFCNT_IN6(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct sioc_mif_req6) & 0x1fff) << 16) | ((('u')) <<
8) | ((107)))
:
259 NET_RLOCK_IN_IOCTL()do { rw_enter_read(&netlock); } while (0);
260 error = get_mif6_cnt((struct sioc_mif_req6 *)data,
261 inp->inp_rtableid);
262 NET_RUNLOCK_IN_IOCTL()do { rw_exit_read(&netlock); } while (0);
263 break;
264 default:
265 error = ENOTTY25;
266 break;
267 }
268 return error;
269}
270
271/*
272 * returns the packet, byte, rpf-failure count for the source group provided
273 */
274int
275get_sg6_cnt(struct sioc_sg_req6 *req, unsigned int rtableid)
276{
277 struct rtentry *rt;
278 struct mf6c *mf6c;
279
280 rt = mf6c_find(NULL((void *)0), &req->src.sin6_addr, &req->grp.sin6_addr,
281 rtableid);
282 if (rt == NULL((void *)0)) {
283 req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff;
284 return EADDRNOTAVAIL49;
285 }
286
287 req->pktcnt = req->bytecnt = req->wrong_if = 0;
288 do {
289 mf6c = (struct mf6c *)rt->rt_llinfo;
290 if (mf6c == NULL((void *)0))
291 continue;
292
293 req->pktcnt += mf6c->mf6c_pkt_cnt;
294 req->bytecnt += mf6c->mf6c_byte_cnt;
295 req->wrong_if += mf6c->mf6c_wrong_if;
296 } while ((rt = rtable_iterate(rt)) != NULL((void *)0));
297
298 return 0;
299}
300
301/*
302 * returns the input and output packet and byte counts on the mif provided
303 */
304int
305get_mif6_cnt(struct sioc_mif_req6 *req, unsigned int rtableid)
306{
307 struct ifnet *ifp;
308 struct mif6 *m6;
309
310 if ((ifp = mrt6_iflookupbymif(req->mifi, rtableid)) == NULL((void *)0))
311 return EINVAL22;
312
313 m6 = (struct mif6 *)ifp->if_mcast6;
314 req->icount = m6->m6_pkt_in;
315 req->ocount = m6->m6_pkt_out;
316 req->ibytes = m6->m6_bytes_in;
317 req->obytes = m6->m6_bytes_out;
318
319 return 0;
320}
321
322int
323mrt6_sysctl_mif(void *oldp, size_t *oldlenp)
324{
325 struct ifnet *ifp;
326 caddr_t where = oldp;
327 size_t needed, given;
328 struct mif6 *mifp;
329 struct mif6info minfo;
330
331 given = *oldlenp;
332 needed = 0;
333 memset(&minfo, 0, sizeof minfo)__builtin_memset((&minfo), (0), (sizeof minfo));
334 TAILQ_FOREACH(ifp, &ifnet, if_list)for((ifp) = ((&ifnet)->tqh_first); (ifp) != ((void *)0
); (ifp) = ((ifp)->if_list.tqe_next))
{
335 if ((mifp = (struct mif6 *)ifp->if_mcast6) == NULL((void *)0))
336 continue;
337
338 minfo.m6_mifi = mifp->m6_mifi;
339 minfo.m6_flags = mifp->m6_flags;
340 minfo.m6_lcl_addr = mifp->m6_lcl_addr;
341 minfo.m6_ifindex = ifp->if_index;
342 minfo.m6_pkt_in = mifp->m6_pkt_in;
343 minfo.m6_pkt_out = mifp->m6_pkt_out;
344 minfo.m6_bytes_in = mifp->m6_bytes_in;
345 minfo.m6_bytes_out = mifp->m6_bytes_out;
346 minfo.m6_rate_limit = mifp->m6_rate_limit;
347
348 needed += sizeof(minfo);
349 if (where && needed <= given) {
350 int error;
351
352 error = copyout(&minfo, where, sizeof(minfo));
353 if (error)
354 return (error);
355 where += sizeof(minfo);
356 }
357 }
358 if (where) {
359 *oldlenp = needed;
360 if (given < needed)
361 return (ENOMEM12);
362 } else
363 *oldlenp = (11 * needed) / 10;
364
365 return (0);
366}
367
368struct mf6csysctlarg {
369 struct mf6cinfo *ms6a_minfos;
370 size_t ms6a_len;
371 size_t ms6a_needed;
372};
373
374int
375mrt6_rtwalk_mf6csysctl(struct rtentry *rt, void *arg, unsigned int rtableid)
376{
377 struct mf6c *mf6c = (struct mf6c *)rt->rt_llinfo;
378 struct mf6csysctlarg *msa = arg;
379 struct ifnet *ifp;
380 struct mif6 *m6;
381 struct mf6cinfo *minfo;
382 int new = 0;
383
384 /* Skip entries being removed. */
385 if (mf6c == NULL((void *)0))
386 return 0;
387
388 /* Skip non-multicast routes. */
389 if (ISSET(rt->rt_flags, RTF_HOST | RTF_MULTICAST)((rt->rt_flags) & (0x4 | 0x200)) !=
390 (RTF_HOST0x4 | RTF_MULTICAST0x200))
391 return 0;
392
393 /* User just asked for the output size. */
394 if (msa->ms6a_minfos == NULL((void *)0)) {
395 msa->ms6a_needed += sizeof(*minfo);
396 return 0;
397 }
398
399 /* Skip route with invalid interfaces. */
400 if ((ifp = if_get(rt->rt_ifidx)) == NULL((void *)0))
401 return 0;
402 if ((m6 = (struct mif6 *)ifp->if_mcast6) == NULL((void *)0)) {
403 if_put(ifp);
404 return 0;
405 }
406
407 for (minfo = msa->ms6a_minfos;
408 (uint8_t *)minfo < ((uint8_t *)msa->ms6a_minfos + msa->ms6a_len);
409 minfo++) {
410 /* Find a new entry or update old entry. */
411 if (!IN6_ARE_ADDR_EQUAL(&minfo->mf6c_origin.sin6_addr,(__builtin_memcmp((&(&minfo->mf6c_origin.sin6_addr
)->__u6_addr.__u6_addr8[0]), (&(&satosin6(rt->rt_gateway
)->sin6_addr)->__u6_addr.__u6_addr8[0]), (sizeof(struct
in6_addr))) == 0)
412 &satosin6(rt->rt_gateway)->sin6_addr)(__builtin_memcmp((&(&minfo->mf6c_origin.sin6_addr
)->__u6_addr.__u6_addr8[0]), (&(&satosin6(rt->rt_gateway
)->sin6_addr)->__u6_addr.__u6_addr8[0]), (sizeof(struct
in6_addr))) == 0)
||
413 !IN6_ARE_ADDR_EQUAL(&minfo->mf6c_mcastgrp.sin6_addr,(__builtin_memcmp((&(&minfo->mf6c_mcastgrp.sin6_addr
)->__u6_addr.__u6_addr8[0]), (&(&satosin6(((rt)->
rt_dest))->sin6_addr)->__u6_addr.__u6_addr8[0]), (sizeof
(struct in6_addr))) == 0)
414 &satosin6(rt_key(rt))->sin6_addr)(__builtin_memcmp((&(&minfo->mf6c_mcastgrp.sin6_addr
)->__u6_addr.__u6_addr8[0]), (&(&satosin6(((rt)->
rt_dest))->sin6_addr)->__u6_addr.__u6_addr8[0]), (sizeof
(struct in6_addr))) == 0)
) {
415 if (!IN6_IS_ADDR_UNSPECIFIED(((*(const u_int32_t *)(const void *)(&(&minfo->mf6c_origin
.sin6_addr)->__u6_addr.__u6_addr8[0]) == 0) && (*(
const u_int32_t *)(const void *)(&(&minfo->mf6c_origin
.sin6_addr)->__u6_addr.__u6_addr8[4]) == 0) && (*(
const u_int32_t *)(const void *)(&(&minfo->mf6c_origin
.sin6_addr)->__u6_addr.__u6_addr8[8]) == 0) && (*(
const u_int32_t *)(const void *)(&(&minfo->mf6c_origin
.sin6_addr)->__u6_addr.__u6_addr8[12]) == 0))
416 &minfo->mf6c_origin.sin6_addr)((*(const u_int32_t *)(const void *)(&(&minfo->mf6c_origin
.sin6_addr)->__u6_addr.__u6_addr8[0]) == 0) && (*(
const u_int32_t *)(const void *)(&(&minfo->mf6c_origin
.sin6_addr)->__u6_addr.__u6_addr8[4]) == 0) && (*(
const u_int32_t *)(const void *)(&(&minfo->mf6c_origin
.sin6_addr)->__u6_addr.__u6_addr8[8]) == 0) && (*(
const u_int32_t *)(const void *)(&(&minfo->mf6c_origin
.sin6_addr)->__u6_addr.__u6_addr8[12]) == 0))
||
417 !IN6_IS_ADDR_UNSPECIFIED(((*(const u_int32_t *)(const void *)(&(&minfo->mf6c_mcastgrp
.sin6_addr)->__u6_addr.__u6_addr8[0]) == 0) && (*(
const u_int32_t *)(const void *)(&(&minfo->mf6c_mcastgrp
.sin6_addr)->__u6_addr.__u6_addr8[4]) == 0) && (*(
const u_int32_t *)(const void *)(&(&minfo->mf6c_mcastgrp
.sin6_addr)->__u6_addr.__u6_addr8[8]) == 0) && (*(
const u_int32_t *)(const void *)(&(&minfo->mf6c_mcastgrp
.sin6_addr)->__u6_addr.__u6_addr8[12]) == 0))
418 &minfo->mf6c_mcastgrp.sin6_addr)((*(const u_int32_t *)(const void *)(&(&minfo->mf6c_mcastgrp
.sin6_addr)->__u6_addr.__u6_addr8[0]) == 0) && (*(
const u_int32_t *)(const void *)(&(&minfo->mf6c_mcastgrp
.sin6_addr)->__u6_addr.__u6_addr8[4]) == 0) && (*(
const u_int32_t *)(const void *)(&(&minfo->mf6c_mcastgrp
.sin6_addr)->__u6_addr.__u6_addr8[8]) == 0) && (*(
const u_int32_t *)(const void *)(&(&minfo->mf6c_mcastgrp
.sin6_addr)->__u6_addr.__u6_addr8[12]) == 0))
)
419 continue;
420
421 new = 1;
422 }
423
424 minfo->mf6c_origin = *satosin6(rt->rt_gateway);
425 minfo->mf6c_mcastgrp = *satosin6(rt_key(rt)((rt)->rt_dest));
426 minfo->mf6c_parent = mf6c->mf6c_parent;
427 minfo->mf6c_pkt_cnt += mf6c->mf6c_pkt_cnt;
428 minfo->mf6c_byte_cnt += mf6c->mf6c_byte_cnt;
429 IF_SET(m6->m6_mifi, &minfo->mf6c_ifset)((&minfo->mf6c_ifset)->ifs_bits[(m6->m6_mifi)/(sizeof
(uint32_t) * 8)] |= (1U << ((m6->m6_mifi) % (sizeof(
uint32_t) * 8))))
;
430 break;
431 }
432
433 if (new != 0)
434 msa->ms6a_needed += sizeof(*minfo);
435
436 if_put(ifp);
437
438 return 0;
439}
440
441int
442mrt6_sysctl_mfc(void *oldp, size_t *oldlenp)
443{
444 unsigned int rtableid;
445 int error;
446 struct mf6csysctlarg msa;
447
448 if (oldp != NULL((void *)0) && *oldlenp > MAXPHYS(64 * 1024))
449 return EINVAL22;
450
451 if (oldp != NULL((void *)0))
452 msa.ms6a_minfos = malloc(*oldlenp, M_TEMP127, M_WAITOK0x0001 | M_ZERO0x0008);
453 else
454 msa.ms6a_minfos = NULL((void *)0);
455
456 msa.ms6a_len = *oldlenp;
457 msa.ms6a_needed = 0;
458
459 for (rtableid = 0; rtableid <= RT_TABLEID_MAX255; rtableid++) {
460 rtable_walk(rtableid, AF_INET624, NULL((void *)0), mrt6_rtwalk_mf6csysctl,
461 &msa);
462 }
463
464 if (msa.ms6a_minfos != NULL((void *)0) && msa.ms6a_needed > 0 &&
465 (error = copyout(msa.ms6a_minfos, oldp, msa.ms6a_needed)) != 0) {
466 free(msa.ms6a_minfos, M_TEMP127, *oldlenp);
467 return error;
468 }
469
470 free(msa.ms6a_minfos, M_TEMP127, *oldlenp);
471 *oldlenp = msa.ms6a_needed;
472
473 return 0;
474}
475
476/*
477 * Enable multicast routing
478 */
479int
480ip6_mrouter_init(struct socket *so, int v, int cmd)
481{
482 struct inpcb *inp = sotoinpcb(so)((struct inpcb *)(so)->so_pcb);
483 unsigned int rtableid = inp->inp_rtableid;
484
485 if (so->so_type != SOCK_RAW3 ||
486 so->so_proto->pr_protocol != IPPROTO_ICMPV658)
487 return (EOPNOTSUPP45);
488
489 if (v != 1)
490 return (ENOPROTOOPT42);
491
492 if (ip6_mrouter[rtableid] != NULL((void *)0))
493 return (EADDRINUSE48);
494
495 ip6_mrouter[rtableid] = so;
496 ip6_mrouter_ver = cmd;
497 mrouter6q[rtableid] = rt_timer_queue_create(MCAST_EXPIRE_TIMEOUT30);
498
499 return (0);
500}
501
502int
503mrouter6_rtwalk_delete(struct rtentry *rt, void *arg, unsigned int rtableid)
504{
505 /* Skip non-multicast routes. */
506 if (ISSET(rt->rt_flags, RTF_HOST | RTF_MULTICAST)((rt->rt_flags) & (0x4 | 0x200)) !=
507 (RTF_HOST0x4 | RTF_MULTICAST0x200))
508 return 0;
509
510 return EEXIST17;
511}
512
513/*
514 * Disable multicast routing
515 */
516int
517ip6_mrouter_done(struct socket *so)
518{
519 struct inpcb *inp = sotoinpcb(so)((struct inpcb *)(so)->so_pcb);
520 struct ifnet *ifp;
521 unsigned int rtableid = inp->inp_rtableid;
522 int error;
523
524 NET_ASSERT_LOCKED()do { int _s = rw_status(&netlock); if ((splassert_ctl >
0) && (_s != 0x0001UL && _s != 0x0002UL)) splassert_fail
(0x0002UL, _s, __func__); } while (0)
;
525
526 /* Delete all remaining installed multicast routes. */
527 do {
528 struct rtentry *rt = NULL((void *)0);
529
530 error = rtable_walk(rtableid, AF_INET624, &rt,
531 mrouter6_rtwalk_delete, NULL((void *)0));
532 if (rt != NULL((void *)0) && error == EEXIST17) {
533 mrt6_mcast_del(rt, rtableid);
534 error = EAGAIN35;
535 }
536 rtfree(rt);
537 } while (error == EAGAIN35);
538
539 /* Unregister all interfaces in the domain. */
540 TAILQ_FOREACH(ifp, &ifnet, if_list)for((ifp) = ((&ifnet)->tqh_first); (ifp) != ((void *)0
); (ifp) = ((ifp)->if_list.tqe_next))
{
541 if (ifp->if_rdomainif_data.ifi_rdomain != rtableid)
542 continue;
543
544 ip6_mrouter_detach(ifp);
545 }
546
547 rt_timer_queue_destroy(mrouter6q[rtableid]);
548 ip6_mrouter[inp->inp_rtableid] = NULL((void *)0);
549 ip6_mrouter_ver = 0;
550 mrouter6q[rtableid] = NULL((void *)0);
551
552 return 0;
553}
554
555void
556ip6_mrouter_detach(struct ifnet *ifp)
557{
558 struct mif6 *m6 = (struct mif6 *)ifp->if_mcast6;
559 struct in6_ifreq ifr;
560
561 if (m6 == NULL((void *)0))
562 return;
563
564 ifp->if_mcast6 = NULL((void *)0);
565
566 memset(&ifr, 0, sizeof(ifr))__builtin_memset((&ifr), (0), (sizeof(ifr)));
567 ifr.ifr_addrifr_ifru.ifru_addr.sin6_family = AF_INET624;
568 ifr.ifr_addrifr_ifru.ifru_addr.sin6_addr = in6addr_any;
569 KERNEL_LOCK()_kernel_lock();
570 (*ifp->if_ioctl)(ifp, SIOCDELMULTI((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((50)))
, (caddr_t)&ifr);
571 KERNEL_UNLOCK()_kernel_unlock();
572
573 free(m6, M_MRTABLE56, sizeof(*m6));
574}
575
576/*
577 * Add a mif to the mif table
578 */
579int
580add_m6if(struct socket *so, struct mif6ctl *mifcp)
581{
582 struct inpcb *inp = sotoinpcb(so)((struct inpcb *)(so)->so_pcb);
583 struct mif6 *mifp;
584 struct ifnet *ifp;
585 struct in6_ifreq ifr;
586 int error;
587 unsigned int rtableid = inp->inp_rtableid;
588
589 NET_ASSERT_LOCKED()do { int _s = rw_status(&netlock); if ((splassert_ctl >
0) && (_s != 0x0001UL && _s != 0x0002UL)) splassert_fail
(0x0002UL, _s, __func__); } while (0)
;
590
591 if (mifcp->mif6c_mifi >= MAXMIFS64)
592 return EINVAL22;
593
594 if (mrt6_iflookupbymif(mifcp->mif6c_mifi, rtableid) != NULL((void *)0))
595 return EADDRINUSE48; /* XXX: is it appropriate? */
596
597 {
598 ifp = if_get(mifcp->mif6c_pifi);
599 if (ifp == NULL((void *)0))
600 return ENXIO6;
601
602 /* Make sure the interface supports multicast */
603 if ((ifp->if_flags & IFF_MULTICAST0x8000) == 0) {
604 if_put(ifp);
605 return EOPNOTSUPP45;
606 }
607
608 /*
609 * Enable promiscuous reception of all IPv6 multicasts
610 * from the interface.
611 */
612 memset(&ifr, 0, sizeof(ifr))__builtin_memset((&ifr), (0), (sizeof(ifr)));
613 ifr.ifr_addrifr_ifru.ifru_addr.sin6_family = AF_INET624;
614 ifr.ifr_addrifr_ifru.ifru_addr.sin6_addr = in6addr_any;
615 error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((49)))
, (caddr_t)&ifr);
616
617 if (error) {
618 if_put(ifp);
619 return error;
620 }
621 }
622
623 mifp = malloc(sizeof(*mifp), M_MRTABLE56, M_WAITOK0x0001 | M_ZERO0x0008);
624 ifp->if_mcast6 = (caddr_t)mifp;
625 mifp->m6_mifi = mifcp->mif6c_mifi;
626 mifp->m6_flags = mifcp->mif6c_flags;
627#ifdef notyet
628 /* scaling up here allows division by 1024 in critical code */
629 mifp->m6_rate_limit = mifcp->mif6c_rate_limit * 1024 / 1000;
630#endif
631
632 if_put(ifp);
633
634 return 0;
635}
636
637/*
638 * Delete a mif from the mif table
639 */
640int
641del_m6if(struct socket *so, mifi_t *mifip)
642{
643 struct inpcb *inp = sotoinpcb(so)((struct inpcb *)(so)->so_pcb);
644 struct ifnet *ifp;
645
646 NET_ASSERT_LOCKED()do { int _s = rw_status(&netlock); if ((splassert_ctl >
0) && (_s != 0x0001UL && _s != 0x0002UL)) splassert_fail
(0x0002UL, _s, __func__); } while (0)
;
647
648 if (*mifip >= MAXMIFS64)
649 return EINVAL22;
650 if ((ifp = mrt6_iflookupbymif(*mifip, inp->inp_rtableid)) == NULL((void *)0))
651 return EINVAL22;
652
653 ip6_mrouter_detach(ifp);
654
655 return 0;
656}
657
658int
659mf6c_add_route(struct ifnet *ifp, struct sockaddr *origin,
660 struct sockaddr *group, struct mf6cctl *mf6cc, int wait)
661{
662 struct rtentry *rt;
663 struct mf6c *mf6c;
664 unsigned int rtableid = ifp->if_rdomainif_data.ifi_rdomain;
665#ifdef MCAST_DEBUG
666 char bsrc[INET6_ADDRSTRLEN46], bdst[INET6_ADDRSTRLEN46];
667#endif /* MCAST_DEBUG */
668
669 rt = mrt6_mcast_add(ifp, origin, group);
670 if (rt == NULL((void *)0))
671 return ENOENT2;
672
673 mf6c = malloc(sizeof(*mf6c), M_MRTABLE56, wait | M_ZERO0x0008);
674 if (mf6c == NULL((void *)0)) {
675 DPRINTF("origin %s group %s parent %d (%s) malloc failed",do { } while (0)
676 inet_ntop(AF_INET6, origin, bsrc, sizeof(bsrc)),do { } while (0)
677 inet_ntop(AF_INET6, group, bdst, sizeof(bdst)),do { } while (0)
678 mf6cc->mf6cc_parent, ifp->if_xname)do { } while (0);
679 mrt6_mcast_del(rt, rtableid);
680 rtfree(rt);
681 return ENOMEM12;
682 }
683
684 rt->rt_llinfo = (caddr_t)mf6c;
685 rt_timer_add(rt, mf6c_expire_route, mrouter6q[rtableid], rtableid);
686 mf6c->mf6c_parent = mf6cc->mf6cc_parent;
687 rtfree(rt);
688
689 return 0;
690}
691
692void
693mf6c_update(struct mf6cctl *mf6cc, int wait, unsigned int rtableid)
694{
695 struct rtentry *rt;
696 struct mf6c *mf6c;
697 struct ifnet *ifp;
698 struct sockaddr_in6 osin6, gsin6;
699 mifi_t mifi;
700#ifdef MCAST_DEBUG
701 char bdst[INET6_ADDRSTRLEN46];
702#endif /* MCAST_DEBUG */
703
704 memset(&osin6, 0, sizeof(osin6))__builtin_memset((&osin6), (0), (sizeof(osin6)));
705 osin6.sin6_family = AF_INET624;
706 osin6.sin6_len = sizeof(osin6);
707 osin6.sin6_addr = mf6cc->mf6cc_origin.sin6_addr;
708
709 memset(&gsin6, 0, sizeof(gsin6))__builtin_memset((&gsin6), (0), (sizeof(gsin6)));
710 gsin6.sin6_family = AF_INET624;
711 gsin6.sin6_len = sizeof(gsin6);
712 gsin6.sin6_addr = mf6cc->mf6cc_mcastgrp.sin6_addr;
713
714 for (mifi = 0; mifi < MAXMIFS64; mifi++) {
715 if (mifi == mf6cc->mf6cc_parent)
716 continue;
717
718 /* Test for mif existence and then update the entry. */
719 if ((ifp = mrt6_iflookupbymif(mifi, rtableid)) == NULL((void *)0))
720 continue;
721
722 rt = mf6c_find(ifp, &mf6cc->mf6cc_origin.sin6_addr,
723 &mf6cc->mf6cc_mcastgrp.sin6_addr, rtableid);
724
725 /* mif not configured or removed. */
726 if (!IF_ISSET(mifi, &mf6cc->mf6cc_ifset)((&mf6cc->mf6cc_ifset)->ifs_bits[(mifi)/(sizeof(uint32_t
) * 8)] & (1U << ((mifi) % (sizeof(uint32_t) * 8)))
)
) {
727 /* Route doesn't exist, nothing to do. */
728 if (rt == NULL((void *)0))
729 continue;
730
731 DPRINTF("del route (group %s) for mif %d (%s)",do { } while (0)
732 inet_ntop(AF_INET6,do { } while (0)
733 &mf6cc->mf6cc_mcastgrp.sin6_addr, bdst,do { } while (0)
734 sizeof(bdst)), mifi, ifp->if_xname)do { } while (0);
735 mrt6_mcast_del(rt, rtableid);
736 rtfree(rt);
737 continue;
738 }
739
740 /* Route exists, look for changes. */
741 if (rt != NULL((void *)0)) {
742 mf6c = (struct mf6c *)rt->rt_llinfo;
743 /* Skip route being deleted. */
744 if (mf6c == NULL((void *)0)) {
745 rtfree(rt);
746 continue;
747 }
748
749 /* No new changes to apply. */
750 if (mf6cc->mf6cc_parent == mf6c->mf6c_parent) {
751 rtfree(rt);
752 continue;
753 }
754
755 DPRINTF("update route (group %s) for mif %d (%s)",do { } while (0)
756 inet_ntop(AF_INET6,do { } while (0)
757 &mf6cc->mf6cc_mcastgrp.sin6_addr, bdst,do { } while (0)
758 sizeof(bdst)), mifi, ifp->if_xname)do { } while (0);
759
760 mf6c->mf6c_parent = mf6cc->mf6cc_parent;
761 rtfree(rt);
762 continue;
763 }
764
765 DPRINTF("add route (group %s) for mif %d (%s)",do { } while (0)
766 inet_ntop(AF_INET6, &mf6cc->mf6cc_mcastgrp.sin6_addr,do { } while (0)
767 bdst, sizeof(bdst)), mifi, ifp->if_xname)do { } while (0);
768
769 mf6c_add_route(ifp, sin6tosa(&osin6), sin6tosa(&gsin6),
770 mf6cc, wait);
771 }
772
773 /* Create route for the parent interface. */
774 if ((ifp = mrt6_iflookupbymif(mf6cc->mf6cc_parent,
775 rtableid)) == NULL((void *)0)) {
776 DPRINTF("failed to find upstream interface %d",do { } while (0)
777 mf6cc->mf6cc_parent)do { } while (0);
778 return;
779 }
780
781 /* We already have a route, nothing to do here. */
782 if ((rt = mf6c_find(ifp, &mf6cc->mf6cc_origin.sin6_addr,
783 &mf6cc->mf6cc_mcastgrp.sin6_addr, rtableid)) != NULL((void *)0)) {
784 rtfree(rt);
785 return;
786 }
787
788 DPRINTF("add upstream route (group %s) for if %s",do { } while (0)
789 inet_ntop(AF_INET6, &mf6cc->mf6cc_mcastgrp.sin6_addr,do { } while (0)
790 bdst, sizeof(bdst)), ifp->if_xname)do { } while (0);
791 mf6c_add_route(ifp, sin6tosa(&osin6), sin6tosa(&gsin6), mf6cc, wait);
792}
793
794int
795mf6c_add(struct mf6cctl *mfccp, struct in6_addr *origin,
796 struct in6_addr *group, int vidx, unsigned int rtableid, int wait)
797{
798 struct ifnet *ifp;
799 struct mif6 *m6;
800 struct mf6cctl mf6cc;
801
802 ifp = mrt6_iflookupbymif(vidx, rtableid);
803 if (ifp == NULL((void *)0) ||
804 (m6 = (struct mif6 *)ifp->if_mcast6) == NULL((void *)0))
805 return ENOENT2;
806
807 memset(&mf6cc, 0, sizeof(mf6cc))__builtin_memset((&mf6cc), (0), (sizeof(mf6cc)));
808 if (mfccp == NULL((void *)0)) {
809 mf6cc.mf6cc_origin.sin6_family = AF_INET624;
810 mf6cc.mf6cc_origin.sin6_len = sizeof(mf6cc.mf6cc_origin);
811 mf6cc.mf6cc_origin.sin6_addr = *origin;
812 mf6cc.mf6cc_mcastgrp.sin6_family = AF_INET624;
813 mf6cc.mf6cc_mcastgrp.sin6_len = sizeof(mf6cc.mf6cc_mcastgrp);
814 mf6cc.mf6cc_mcastgrp.sin6_addr = *group;
815 mf6cc.mf6cc_parent = vidx;
816 } else
817 memcpy(&mf6cc, mfccp, sizeof(mf6cc))__builtin_memcpy((&mf6cc), (mfccp), (sizeof(mf6cc)));
818
819 mf6c_update(&mf6cc, wait, rtableid);
820
821 return 0;
822}
823
824int
825add_m6fc(struct socket *so, struct mf6cctl *mfccp)
826{
827 struct inpcb *inp = sotoinpcb(so)((struct inpcb *)(so)->so_pcb);
828 unsigned int rtableid = inp->inp_rtableid;
829
830 NET_ASSERT_LOCKED()do { int _s = rw_status(&netlock); if ((splassert_ctl >
0) && (_s != 0x0001UL && _s != 0x0002UL)) splassert_fail
(0x0002UL, _s, __func__); } while (0)
;
831
832 return mf6c_add(mfccp, &mfccp->mf6cc_origin.sin6_addr,
833 &mfccp->mf6cc_mcastgrp.sin6_addr, mfccp->mf6cc_parent,
834 rtableid, M_WAITOK0x0001);
835}
836
837int
838del_m6fc(struct socket *so, struct mf6cctl *mfccp)
839{
840 struct inpcb *inp = sotoinpcb(so)((struct inpcb *)(so)->so_pcb);
841 struct rtentry *rt;
842 unsigned int rtableid = inp->inp_rtableid;
843
844 NET_ASSERT_LOCKED()do { int _s = rw_status(&netlock); if ((splassert_ctl >
0) && (_s != 0x0001UL && _s != 0x0002UL)) splassert_fail
(0x0002UL, _s, __func__); } while (0)
;
845
846 while ((rt = mf6c_find(NULL((void *)0), &mfccp->mf6cc_origin.sin6_addr,
847 &mfccp->mf6cc_mcastgrp.sin6_addr, rtableid)) != NULL((void *)0)) {
848 mrt6_mcast_del(rt, rtableid);
849 rtfree(rt);
850 }
851
852 return 0;
853}
854
855int
856socket6_send(struct socket *s, struct mbuf *mm, struct sockaddr_in6 *src)
857{
858 if (s) {
859 if (sbappendaddr(s, &s->so_rcv, sin6tosa(src), mm, NULL((void *)0)) != 0) {
860 sorwakeup(s);
861 return 0;
862 }
863 }
864 m_freem(mm);
865 return -1;
866}
867
868/*
869 * IPv6 multicast forwarding function. This function assumes that the packet
870 * pointed to by "ip6" has arrived on (or is about to be sent to) the interface
871 * pointed to by "ifp", and the packet is to be relayed to other networks
872 * that have members of the packet's destination IPv6 multicast group.
873 *
874 * The packet is returned unscathed to the caller, unless it is
875 * erroneous, in which case a non-zero return value tells the caller to
876 * discard it.
877 */
878int
879ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m)
880{
881 struct rtentry *rt;
882 struct mif6 *mifp;
883 struct mbuf *mm;
884 struct sockaddr_in6 sin6;
885 unsigned int rtableid = ifp->if_rdomainif_data.ifi_rdomain;
886
887 NET_ASSERT_LOCKED()do { int _s = rw_status(&netlock); if ((splassert_ctl >
0) && (_s != 0x0001UL && _s != 0x0002UL)) splassert_fail
(0x0002UL, _s, __func__); } while (0)
;
888
889 /*
890 * Don't forward a packet with Hop limit of zero or one,
891 * or a packet destined to a local-only group.
892 */
893 if (ip6->ip6_hlimip6_ctlun.ip6_un1.ip6_un1_hlim <= 1 || IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst)(((&ip6->ip6_dst)->__u6_addr.__u6_addr8[0] == 0xff)
&& (((&ip6->ip6_dst)->__u6_addr.__u6_addr8
[1] & 0x0f) == 0x01))
||
894 IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst)(((&ip6->ip6_dst)->__u6_addr.__u6_addr8[0] == 0xff)
&& (((&ip6->ip6_dst)->__u6_addr.__u6_addr8
[1] & 0x0f) == 0x02))
)
895 return 0;
896 ip6->ip6_hlimip6_ctlun.ip6_un1.ip6_un1_hlim--;
897
898 /*
899 * Source address check: do not forward packets with unspecified
900 * source. It was discussed in July 2000, on ipngwg mailing list.
901 * This is rather more serious than unicast cases, because some
902 * MLD packets can be sent with the unspecified source address
903 * (although such packets must normally set 1 to the hop limit field).
904 */
905 if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)((*(const u_int32_t *)(const void *)(&(&ip6->ip6_src
)->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t
*)(const void *)(&(&ip6->ip6_src)->__u6_addr.__u6_addr8
[4]) == 0) && (*(const u_int32_t *)(const void *)(&
(&ip6->ip6_src)->__u6_addr.__u6_addr8[8]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&ip6->ip6_src
)->__u6_addr.__u6_addr8[12]) == 0))
) {
906 ip6stat_inc(ip6s_cantforward);
907 if (ip6_log_time + ip6_log_interval < getuptime()) {
908 char src[INET6_ADDRSTRLEN46], dst[INET6_ADDRSTRLEN46];
909
910 ip6_log_time = getuptime();
911
912 inet_ntop(AF_INET624, &ip6->ip6_src, src, sizeof(src));
913 inet_ntop(AF_INET624, &ip6->ip6_dst, dst, sizeof(dst));
914 log(LOG_DEBUG7, "cannot forward "
915 "from %s to %s nxt %d received on interface %u\n",
916 src, dst, ip6->ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt, m->m_pkthdrM_dat.MH.MH_pkthdr.ph_ifidx);
917 }
918 return 0;
919 }
920
921 /*
922 * Determine forwarding mifs from the forwarding cache table
923 */
924 rt = mf6c_find(NULL((void *)0), &ip6->ip6_src, &ip6->ip6_dst, rtableid);
925
926 /* Entry exists, so forward if necessary */
927 if (rt) {
928 return (ip6_mdq(m, ifp, rt));
929 } else {
930 /*
931 * If we don't have a route for packet's origin,
932 * Make a copy of the packet &
933 * send message to routing daemon
934 */
935
936 mrt6stat.mrt6s_no_route++;
937
938 {
939 struct mrt6msg *im;
940
941 if ((mifp = (struct mif6 *)ifp->if_mcast6) == NULL((void *)0))
942 return EHOSTUNREACH65;
943
944 /*
945 * Make a copy of the header to send to the user
946 * level process
947 */
948 mm = m_copym(m, 0, sizeof(struct ip6_hdr), M_NOWAIT0x0002);
949 if (mm == NULL((void *)0))
950 return ENOBUFS55;
951
952 /*
953 * Send message to routing daemon
954 */
955 (void)memset(&sin6, 0, sizeof(sin6))__builtin_memset((&sin6), (0), (sizeof(sin6)));
956 sin6.sin6_len = sizeof(sin6);
957 sin6.sin6_family = AF_INET624;
958 sin6.sin6_addr = ip6->ip6_src;
959
960 im = NULL((void *)0);
961 switch (ip6_mrouter_ver) {
962 case MRT6_INIT108:
963 im = mtod(mm, struct mrt6msg *)((struct mrt6msg *)((mm)->m_hdr.mh_data));
964 im->im6_msgtype = MRT6MSG_NOCACHE1;
965 im->im6_mbz = 0;
966 im->im6_mif = mifp->m6_mifi;
967 break;
968 default:
969 m_freem(mm);
970 return EINVAL22;
971 }
972
973 if (socket6_send(ip6_mrouter[rtableid], mm,
974 &sin6) < 0) {
975 log(LOG_WARNING4, "ip6_mforward: ip6_mrouter "
976 "socket queue full\n");
977 mrt6stat.mrt6s_upq_sockfull++;
978 return ENOBUFS55;
979 }
980
981 mrt6stat.mrt6s_upcalls++;
982
983 mf6c_add(NULL((void *)0), &ip6->ip6_src, &ip6->ip6_dst,
984 mifp->m6_mifi, rtableid, M_NOWAIT0x0002);
985 }
986
987 return 0;
988 }
989}
990
991void
992mf6c_expire_route(struct rtentry *rt, struct rttimer *rtt)
993{
994 struct mf6c *mf6c = (struct mf6c *)rt->rt_llinfo;
995 unsigned int rtableid = rtt->rtt_tableid;
996#ifdef MCAST_DEBUG
997 char bsrc[INET6_ADDRSTRLEN46], bdst[INET6_ADDRSTRLEN46];
998#endif /* MCAST_DEBUG */
999
1000 /* Skip entry being deleted. */
1001 if (mf6c == NULL((void *)0))
1002 return;
1003
1004 DPRINTF("origin %s group %s interface %d expire %s",do { } while (0)
1005 inet_ntop(AF_INET6, &satosin6(rt->rt_gateway)->sin6_addr,do { } while (0)
1006 bsrc, sizeof(bsrc)),do { } while (0)
1007 inet_ntop(AF_INET6, &satosin6(rt_key(rt))->sin6_addr,do { } while (0)
1008 bdst, sizeof(bdst)), rt->rt_ifidx,do { } while (0)
1009 mf6c->mf6c_expire ? "yes" : "no")do { } while (0);
1010
1011 if (mf6c->mf6c_expire == 0) {
1012 mf6c->mf6c_expire = 1;
1013 rt_timer_add(rt, mf6c_expire_route, mrouter6q[rtableid],
1014 rtableid);
1015 return;
1016 }
1017
1018 mrt6_mcast_del(rt, rtableid);
1019}
1020
1021/*
1022 * Packet forwarding routine once entry in the cache is made
1023 */
1024int
1025ip6_mdq(struct mbuf *m, struct ifnet *ifp, struct rtentry *rt)
1026{
1027 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data));
1028 struct mif6 *m6, *mifp = (struct mif6 *)ifp->if_mcast6;
1029 struct mf6c *mf6c = (struct mf6c *)rt->rt_llinfo;
1030 struct ifnet *ifn;
1031 int plen = m->m_pkthdrM_dat.MH.MH_pkthdr.len;
1032
1033 if (mifp == NULL((void *)0) || mf6c == NULL((void *)0)) {
1034 rtfree(rt);
1035 return EHOSTUNREACH65;
1036 }
1037
1038 /*
1039 * Don't forward if it didn't arrive from the parent mif
1040 * for its origin.
1041 */
1042 if (mifp->m6_mifi != mf6c->mf6c_parent) {
1043 /* came in the wrong interface */
1044 mrt6stat.mrt6s_wrong_if++;
1045 mf6c->mf6c_wrong_if++;
1046 rtfree(rt);
1047 return 0;
1048 } /* if wrong iif */
1049
1050 /* If I sourced this packet, it counts as output, else it was input. */
1051 if (m->m_pkthdrM_dat.MH.MH_pkthdr.ph_ifidx == 0) {
1052 /* XXX: is ph_ifidx really 0 when output?? */
1053 mifp->m6_pkt_out++;
1054 mifp->m6_bytes_out += plen;
1055 } else {
1056 mifp->m6_pkt_in++;
1057 mifp->m6_bytes_in += plen;
1058 }
1059
1060 /*
1061 * For each mif, forward a copy of the packet if there are group
1062 * members downstream on the interface.
1063 */
1064 do {
1065 /* Don't consider non multicast routes. */
1066 if (ISSET(rt->rt_flags, RTF_HOST | RTF_MULTICAST)((rt->rt_flags) & (0x4 | 0x200)) !=
1067 (RTF_HOST0x4 | RTF_MULTICAST0x200))
1068 continue;
1069
1070 mf6c = (struct mf6c *)rt->rt_llinfo;
1071 if (mf6c == NULL((void *)0))
1072 continue;
1073
1074 mf6c->mf6c_pkt_cnt++;
1075 mf6c->mf6c_byte_cnt += m->m_pkthdrM_dat.MH.MH_pkthdr.len;
1076
1077 /* Don't let this route expire. */
1078 mf6c->mf6c_expire = 0;
1079
1080 if ((ifn = if_get(rt->rt_ifidx)) == NULL((void *)0))
1081 continue;
1082
1083 /* Sanity check: did we configure this? */
1084 if ((m6 = (struct mif6 *)ifn->if_mcast6) == NULL((void *)0)) {
1085 if_put(ifn);
1086 continue;
1087 }
1088
1089 /* Don't send in the upstream interface. */
1090 if (mf6c->mf6c_parent == m6->m6_mifi) {
1091 if_put(ifn);
1092 continue;
1093 }
1094
1095 /*
1096 * check if the outgoing packet is going to break
1097 * a scope boundary.
1098 */
1099 if ((mifp->m6_flags & MIFF_REGISTER0x1) == 0 &&
1100 (m6->m6_flags & MIFF_REGISTER0x1) == 0 &&
1101 (in6_addr2scopeid(ifp->if_index, &ip6->ip6_dst) !=
1102 in6_addr2scopeid(ifn->if_index, &ip6->ip6_dst) ||
1103 in6_addr2scopeid(ifp->if_index, &ip6->ip6_src) !=
1104 in6_addr2scopeid(ifn->if_index, &ip6->ip6_src))) {
1105 if_put(ifn);
1106 ip6stat_inc(ip6s_badscope);
1107 continue;
1108 }
1109
1110 m6->m6_pkt_out++;
1111 m6->m6_bytes_out += plen;
1112
1113 phyint_send6(ifn, ip6, m);
1114 if_put(ifn);
1115 } while ((rt = rtable_iterate(rt)) != NULL((void *)0));
1116
1117 return 0;
1118}
1119
1120void
1121phyint_send6(struct ifnet *ifp, struct ip6_hdr *ip6, struct mbuf *m)
1122{
1123 struct mbuf *mb_copy;
1124 struct sockaddr_in6 *dst6, sin6;
1125 int error = 0;
1126
1127 NET_ASSERT_LOCKED()do { int _s = rw_status(&netlock); if ((splassert_ctl >
0) && (_s != 0x0001UL && _s != 0x0002UL)) splassert_fail
(0x0002UL, _s, __func__); } while (0)
;
1128
1129 /*
1130 * Make a new reference to the packet; make sure that
1131 * the IPv6 header is actually copied, not just referenced,
1132 * so that ip6_output() only scribbles on the copy.
1133 */
1134 mb_copy = m_dup_pkt(m, max_linkhdr, M_NOWAIT0x0002);
1135 if (mb_copy == NULL((void *)0))
1136 return;
1137 /* set MCAST flag to the outgoing packet */
1138 mb_copy->m_flagsm_hdr.mh_flags |= M_MCAST0x0200;
1139
1140 /*
1141 * If we sourced the packet, call ip6_output since we may divide
1142 * the packet into fragments when the packet is too big for the
1143 * outgoing interface.
1144 * Otherwise, we can simply send the packet to the interface
1145 * sending queue.
1146 */
1147 if (m->m_pkthdrM_dat.MH.MH_pkthdr.ph_ifidx == 0) {
1148 struct ip6_moptions im6o;
1149
1150 im6o.im6o_ifidx = ifp->if_index;
1151 /* XXX: ip6_output will override ip6->ip6_hlim */
1152 im6o.im6o_hlim = ip6->ip6_hlimip6_ctlun.ip6_un1.ip6_un1_hlim;
1153 im6o.im6o_loop = 1;
1154 error = ip6_output(mb_copy, NULL((void *)0), NULL((void *)0), IPV6_FORWARDING0x02, &im6o,
1155 NULL((void *)0));
1156 return;
1157 }
1158
1159 /*
1160 * If we belong to the destination multicast group
1161 * on the outgoing interface, loop back a copy.
1162 */
1163 dst6 = &sin6;
1164 memset(&sin6, 0, sizeof(sin6))__builtin_memset((&sin6), (0), (sizeof(sin6)));
1165 if (in6_hasmulti(&ip6->ip6_dst, ifp)) {
1166 dst6->sin6_len = sizeof(struct sockaddr_in6);
1167 dst6->sin6_family = AF_INET624;
1168 dst6->sin6_addr = ip6->ip6_dst;
1169 ip6_mloopback(ifp, m, dst6);
1170 }
1171 /*
1172 * Put the packet into the sending queue of the outgoing interface
1173 * if it would fit in the MTU of the interface.
1174 */
1175 if (mb_copy->m_pkthdrM_dat.MH.MH_pkthdr.len <= ifp->if_mtuif_data.ifi_mtu || ifp->if_mtuif_data.ifi_mtu < IPV6_MMTU1280) {
1176 dst6->sin6_len = sizeof(struct sockaddr_in6);
1177 dst6->sin6_family = AF_INET624;
1178 dst6->sin6_addr = ip6->ip6_dst;
1179 error = ifp->if_output(ifp, mb_copy, sin6tosa(dst6), NULL((void *)0));
Value stored to 'error' is never read
1180 } else {
1181 if (ip6_mcast_pmtu)
1182 icmp6_error(mb_copy, ICMP6_PACKET_TOO_BIG2, 0,
1183 ifp->if_mtuif_data.ifi_mtu);
1184 else {
1185 m_freem(mb_copy); /* simply discard the packet */
1186 }
1187 }
1188}
1189
1190struct ifnet *
1191mrt6_iflookupbymif(mifi_t mifi, unsigned int rtableid)
1192{
1193 struct mif6 *m6;
1194 struct ifnet *ifp;
1195
1196 TAILQ_FOREACH(ifp, &ifnet, if_list)for((ifp) = ((&ifnet)->tqh_first); (ifp) != ((void *)0
); (ifp) = ((ifp)->if_list.tqe_next))
{
1197 if (ifp->if_rdomainif_data.ifi_rdomain != rtableid)
1198 continue;
1199 if ((m6 = (struct mif6 *)ifp->if_mcast6) == NULL((void *)0))
1200 continue;
1201 if (m6->m6_mifi != mifi)
1202 continue;
1203
1204 return ifp;
1205 }
1206
1207 return NULL((void *)0);
1208}
1209
1210struct rtentry *
1211mf6c_find(struct ifnet *ifp, struct in6_addr *origin, struct in6_addr *group,
1212 unsigned int rtableid)
1213{
1214 struct rtentry *rt;
1215 struct sockaddr_in6 msin6;
1216
1217 memset(&msin6, 0, sizeof(msin6))__builtin_memset((&msin6), (0), (sizeof(msin6)));
1218 msin6.sin6_family = AF_INET624;
1219 msin6.sin6_len = sizeof(msin6);
1220 msin6.sin6_addr = *group;
1221
1222 rt = rtalloc(sin6tosa(&msin6), 0, rtableid);
1223 do {
1224 if (!rtisvalid(rt)) {
1225 rtfree(rt);
1226 return NULL((void *)0);
1227 }
1228 if (ISSET(rt->rt_flags, RTF_HOST | RTF_MULTICAST)((rt->rt_flags) & (0x4 | 0x200)) !=
1229 (RTF_HOST0x4 | RTF_MULTICAST0x200))
1230 continue;
1231 /* Return first occurrence if interface is not specified. */
1232 if (ifp == NULL((void *)0))
1233 return rt;
1234 if (rt->rt_ifidx == ifp->if_index)
1235 return rt;
1236 } while ((rt = rtable_iterate(rt)) != NULL((void *)0));
1237
1238 return NULL((void *)0);
1239}
1240
1241struct rtentry *
1242mrt6_mcast_add(struct ifnet *ifp, struct sockaddr *origin,
1243 struct sockaddr *group)
1244{
1245 struct ifaddr *ifa;
1246 int rv;
1247 unsigned int rtableid = ifp->if_rdomainif_data.ifi_rdomain;
1248
1249 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)for((ifa) = ((&ifp->if_addrlist)->tqh_first); (ifa)
!= ((void *)0); (ifa) = ((ifa)->ifa_list.tqe_next))
{
1250 if (ifa->ifa_addr->sa_family == AF_INET624)
1251 break;
1252 }
1253 if (ifa == NULL((void *)0)) {
1254 DPRINTF("ifa == NULL")do { } while (0);
1255 return NULL((void *)0);
1256 }
1257
1258 rv = rt_ifa_add(ifa, RTF_HOST0x4 | RTF_MULTICAST0x200 | RTF_MPATH0x40000, group,
1259 ifp->if_rdomainif_data.ifi_rdomain);
1260 if (rv != 0) {
1261 DPRINTF("rt_ifa_add failed %d", rv)do { } while (0);
1262 return NULL((void *)0);
1263 }
1264
1265 return mf6c_find(ifp, NULL((void *)0), &satosin6(group)->sin6_addr, rtableid);
1266}
1267
1268void
1269mrt6_mcast_del(struct rtentry *rt, unsigned int rtableid)
1270{
1271 struct ifnet *ifp;
1272 int error;
1273
1274 /* Remove all timers related to this route. */
1275 rt_timer_remove_all(rt);
1276
1277 free(rt->rt_llinfo, M_MRTABLE56, sizeof(struct mf6c));
1278 rt->rt_llinfo = NULL((void *)0);
1279
1280 ifp = if_get(rt->rt_ifidx);
1281 if (ifp == NULL((void *)0))
1282 return;
1283 error = rtdeletemsg(rt, ifp, rtableid);
1284 if_put(ifp);
1285
1286 if (error)
1287 DPRINTF("delete route error %d\n", error)do { } while (0);
1288}