in_mcast.c revision 170613
1/*-
2 * Copyright (c) 2007 Bruce M. Simpson.
3 * Copyright (c) 2005 Robert N. M. Watson.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote
15 *    products derived from this software without specific prior written
16 *    permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31/*
32 * IPv4 multicast socket, group, and socket option processing module.
33 * Until further notice, this file requires INET to compile.
34 * TODO: Make this infrastructure independent of address family.
35 * TODO: Teach netinet6 to use this code.
36 * TODO: Hook up SSM logic to IGMPv3/MLDv2.
37 */
38
39#include <sys/cdefs.h>
40__FBSDID("$FreeBSD: head/sys/netinet/in_mcast.c 170613 2007-06-12 16:24:56Z bms $");
41
42#include <sys/param.h>
43#include <sys/systm.h>
44#include <sys/kernel.h>
45#include <sys/malloc.h>
46#include <sys/mbuf.h>
47#include <sys/socket.h>
48#include <sys/socketvar.h>
49#include <sys/sysctl.h>
50
51#include <net/if.h>
52#include <net/if_dl.h>
53#include <net/route.h>
54
55#include <netinet/in.h>
56#include <netinet/in_systm.h>
57#include <netinet/in_pcb.h>
58#include <netinet/in_var.h>
59#include <netinet/ip_var.h>
60#include <netinet/igmp_var.h>
61
62#ifndef __SOCKUNION_DECLARED
63union sockunion {
64	struct sockaddr_storage	ss;
65	struct sockaddr		sa;
66	struct sockaddr_dl	sdl;
67	struct sockaddr_in	sin;
68#ifdef INET6
69	struct sockaddr_in6	sin6;
70#endif
71};
72typedef union sockunion sockunion_t;
73#define __SOCKUNION_DECLARED
74#endif /* __SOCKUNION_DECLARED */
75
76static MALLOC_DEFINE(M_IPMADDR, "in_multi", "IPv4 multicast group");
77static MALLOC_DEFINE(M_IPMOPTS, "ip_moptions", "IPv4 multicast options");
78static MALLOC_DEFINE(M_IPMSOURCE, "in_msource", "IPv4 multicast source filter");
79
80/*
81 * The IPv4 multicast list (in_multihead and associated structures) are
82 * protected by the global in_multi_mtx.  See in_var.h for more details.  For
83 * now, in_multi_mtx is marked as recursible due to IGMP's calling back into
84 * ip_output() to send IGMP packets while holding the lock; this probably is
85 * not quite desirable.
86 */
87struct in_multihead in_multihead;	/* XXX BSS initialization */
88struct mtx in_multi_mtx;
89MTX_SYSINIT(in_multi_mtx, &in_multi_mtx, "in_multi_mtx", MTX_DEF | MTX_RECURSE);
90
91/*
92 * Functions with non-static linkage defined in this file should be
93 * declared in in_var.h:
94 *  imo_match_group()
95 *  imo_match_source()
96 *  in_addmulti()
97 *  in_delmulti()
98 *  in_delmulti_locked()
99 * and ip_var.h:
100 *  inp_freemoptions()
101 *  inp_getmoptions()
102 *  inp_setmoptions()
103 */
104static int	imo_grow(struct ip_moptions *);
105static int	imo_join_source(struct ip_moptions *, size_t, sockunion_t *);
106static int	imo_leave_source(struct ip_moptions *, size_t, sockunion_t *);
107static int	inp_change_source_filter(struct inpcb *, struct sockopt *);
108static struct ip_moptions *
109		inp_findmoptions(struct inpcb *);
110static int	inp_get_source_filters(struct inpcb *, struct sockopt *);
111static int	inp_join_group(struct inpcb *, struct sockopt *);
112static int	inp_leave_group(struct inpcb *, struct sockopt *);
113static int	inp_set_multicast_if(struct inpcb *, struct sockopt *);
114static int	inp_set_source_filters(struct inpcb *, struct sockopt *);
115
116/*
117 * Resize the ip_moptions vector to the next power-of-two minus 1.
118 * May be called with locks held; do not sleep.
119 */
120static int
121imo_grow(struct ip_moptions *imo)
122{
123	struct in_multi		**nmships;
124	struct in_multi		**omships;
125	struct in_mfilter	 *nmfilters;
126	struct in_mfilter	 *omfilters;
127	size_t			  idx;
128	size_t			  newmax;
129	size_t			  oldmax;
130
131	nmships = NULL;
132	nmfilters = NULL;
133	omships = imo->imo_membership;
134	omfilters = imo->imo_mfilters;
135	oldmax = imo->imo_max_memberships;
136	newmax = ((oldmax + 1) * 2) - 1;
137
138	if (newmax <= IP_MAX_MEMBERSHIPS) {
139		nmships = (struct in_multi **)realloc(omships,
140		    sizeof(struct in_multi *) * newmax, M_IPMOPTS, M_NOWAIT);
141		nmfilters = (struct in_mfilter *)realloc(omfilters,
142		    sizeof(struct in_mfilter) * newmax, M_IPMSOURCE, M_NOWAIT);
143		if (nmships != NULL && nmfilters != NULL) {
144			/* Initialize newly allocated source filter heads. */
145			for (idx = oldmax; idx < newmax; idx++) {
146				nmfilters[idx].imf_fmode = MCAST_EXCLUDE;
147				nmfilters[idx].imf_nsources = 0;
148				TAILQ_INIT(&nmfilters[idx].imf_sources);
149			}
150			imo->imo_max_memberships = newmax;
151			imo->imo_membership = nmships;
152			imo->imo_mfilters = nmfilters;
153		}
154	}
155
156	if (nmships == NULL || nmfilters == NULL) {
157		if (nmships != NULL)
158			free(nmships, M_IPMOPTS);
159		if (nmfilters != NULL)
160			free(nmfilters, M_IPMSOURCE);
161		return (ETOOMANYREFS);
162	}
163
164	return (0);
165}
166
167/*
168 * Add a source to a multicast filter list.
169 * Assumes the associated inpcb is locked.
170 */
171static int
172imo_join_source(struct ip_moptions *imo, size_t gidx, sockunion_t *src)
173{
174	struct in_msource	*ims, *nims;
175	struct in_mfilter	*imf;
176
177	KASSERT(src->ss.ss_family == AF_INET, ("%s: !AF_INET", __func__));
178	KASSERT(imo->imo_mfilters != NULL,
179	    ("%s: imo_mfilters vector not allocated", __func__));
180
181	imf = &imo->imo_mfilters[gidx];
182	if (imf->imf_nsources == IP_MAX_SOURCE_FILTER)
183		return (ENOBUFS);
184
185	ims = imo_match_source(imo, gidx, &src->sa);
186	if (ims != NULL)
187		return (EADDRNOTAVAIL);
188
189	/* Do not sleep with inp lock held. */
190	MALLOC(nims, struct in_msource *, sizeof(struct in_msource),
191	    M_IPMSOURCE, M_NOWAIT | M_ZERO);
192	if (nims == NULL)
193		return (ENOBUFS);
194
195	nims->ims_addr = src->ss;
196	TAILQ_INSERT_TAIL(&imf->imf_sources, nims, ims_next);
197	imf->imf_nsources++;
198
199	return (0);
200}
201
202static int
203imo_leave_source(struct ip_moptions *imo, size_t gidx, sockunion_t *src)
204{
205	struct in_msource	*ims;
206	struct in_mfilter	*imf;
207
208	KASSERT(src->ss.ss_family == AF_INET, ("%s: !AF_INET", __func__));
209	KASSERT(imo->imo_mfilters != NULL,
210	    ("%s: imo_mfilters vector not allocated", __func__));
211
212	imf = &imo->imo_mfilters[gidx];
213	if (imf->imf_nsources == IP_MAX_SOURCE_FILTER)
214		return (ENOBUFS);
215
216	ims = imo_match_source(imo, gidx, &src->sa);
217	if (ims == NULL)
218		return (EADDRNOTAVAIL);
219
220	TAILQ_REMOVE(&imf->imf_sources, ims, ims_next);
221	FREE(ims, M_IPMSOURCE);
222	imf->imf_nsources--;
223
224	return (0);
225}
226
227/*
228 * Find an IPv4 multicast group entry for this ip_moptions instance
229 * which matches the specified group, and optionally an interface.
230 * Return its index into the array, or -1 if not found.
231 */
232size_t
233imo_match_group(struct ip_moptions *imo, struct ifnet *ifp,
234    struct sockaddr *group)
235{
236	sockunion_t	 *gsa;
237	struct in_multi	**pinm;
238	int		  idx;
239	int		  nmships;
240
241	gsa = (sockunion_t *)group;
242
243	/* The imo_membership array may be lazy allocated. */
244	if (imo->imo_membership == NULL || imo->imo_num_memberships == 0)
245		return (-1);
246
247	nmships = imo->imo_num_memberships;
248	pinm = &imo->imo_membership[0];
249	for (idx = 0; idx < nmships; idx++, pinm++) {
250		if (*pinm == NULL)
251			continue;
252#if 0
253		printf("%s: trying ifp = %p, inaddr = %s ", __func__,
254		    ifp, inet_ntoa(gsa->sin.sin_addr));
255		printf("against %p, %s\n",
256		    (*pinm)->inm_ifp, inet_ntoa((*pinm)->inm_addr));
257#endif
258		if ((ifp == NULL || ((*pinm)->inm_ifp == ifp)) &&
259		    (*pinm)->inm_addr.s_addr == gsa->sin.sin_addr.s_addr) {
260			break;
261		}
262	}
263	if (idx >= nmships)
264		idx = -1;
265
266	return (idx);
267}
268
269/*
270 * Find a multicast source entry for this imo which matches
271 * the given group index for this socket, and source address.
272 */
273struct in_msource *
274imo_match_source(struct ip_moptions *imo, size_t gidx, struct sockaddr *src)
275{
276	struct in_mfilter	*imf;
277	struct in_msource	*ims, *pims;
278
279	KASSERT(src->sa_family == AF_INET, ("%s: !AF_INET", __func__));
280	KASSERT(gidx != -1 && gidx < imo->imo_num_memberships,
281	    ("%s: invalid index %d\n", __func__, (int)gidx));
282
283	/* The imo_mfilters array may be lazy allocated. */
284	if (imo->imo_mfilters == NULL)
285		return (NULL);
286
287	pims = NULL;
288	imf = &imo->imo_mfilters[gidx];
289	TAILQ_FOREACH(ims, &imf->imf_sources, ims_next) {
290		/*
291		 * Perform bitwise comparison of two IPv4 addresses.
292		 * TODO: Do the same for IPv6.
293		 * Do not use sa_equal() for this as it is not aware of
294		 * deeper structure in sockaddr_in or sockaddr_in6.
295		 */
296		if (((struct sockaddr_in *)&ims->ims_addr)->sin_addr.s_addr ==
297		    ((struct sockaddr_in *)src)->sin_addr.s_addr) {
298			pims = ims;
299			break;
300		}
301	}
302
303	return (pims);
304}
305
306/*
307 * Join an IPv4 multicast group.
308 */
309struct in_multi *
310in_addmulti(struct in_addr *ap, struct ifnet *ifp)
311{
312	struct in_multi *inm;
313
314	inm = NULL;
315
316	IFF_LOCKGIANT(ifp);
317	IN_MULTI_LOCK();
318
319	IN_LOOKUP_MULTI(*ap, ifp, inm);
320	if (inm != NULL) {
321		/*
322		 * If we already joined this group, just bump the
323		 * refcount and return it.
324		 */
325		KASSERT(inm->inm_refcount >= 1,
326		    ("%s: bad refcount %d", __func__, inm->inm_refcount));
327		++inm->inm_refcount;
328	} else do {
329		sockunion_t		 gsa;
330		struct ifmultiaddr	*ifma;
331		struct in_multi		*ninm;
332		int			 error;
333
334		memset(&gsa, 0, sizeof(gsa));
335		gsa.sin.sin_family = AF_INET;
336		gsa.sin.sin_len = sizeof(struct sockaddr_in);
337		gsa.sin.sin_addr = *ap;
338
339		/*
340		 * Check if a link-layer group is already associated
341		 * with this network-layer group on the given ifnet.
342		 * If so, bump the refcount on the existing network-layer
343		 * group association and return it.
344		 */
345		error = if_addmulti(ifp, &gsa.sa, &ifma);
346		if (error)
347			break;
348		if (ifma->ifma_protospec != NULL) {
349			inm = (struct in_multi *)ifma->ifma_protospec;
350#ifdef INVARIANTS
351			if (inm->inm_ifma != ifma || inm->inm_ifp != ifp ||
352			    inm->inm_addr.s_addr != ap->s_addr)
353				panic("%s: ifma is inconsistent", __func__);
354#endif
355			++inm->inm_refcount;
356			break;
357		}
358
359		/*
360		 * A new membership is needed; construct it and
361		 * perform the IGMP join.
362		 */
363		ninm = malloc(sizeof(*ninm), M_IPMADDR, M_NOWAIT | M_ZERO);
364		if (ninm == NULL) {
365			if_delmulti_ifma(ifma);
366			break;
367		}
368		ninm->inm_addr = *ap;
369		ninm->inm_ifp = ifp;
370		ninm->inm_ifma = ifma;
371		ninm->inm_refcount = 1;
372		ifma->ifma_protospec = ninm;
373		LIST_INSERT_HEAD(&in_multihead, ninm, inm_link);
374
375		igmp_joingroup(ninm);
376
377		inm = ninm;
378	} while (0);
379
380	IN_MULTI_UNLOCK();
381	IFF_UNLOCKGIANT(ifp);
382
383	return (inm);
384}
385
386/*
387 * Leave an IPv4 multicast group.
388 * It is OK to call this routine if the underlying ifnet went away.
389 *
390 * XXX: To deal with the ifp going away, we cheat; the link-layer code in net
391 * will set ifma_ifp to NULL when the associated ifnet instance is detached
392 * from the system.
393 *
394 * The only reason we need to violate layers and check ifma_ifp here at all
395 * is because certain hardware drivers still require Giant to be held,
396 * and it must always be taken before other locks.
397 */
398void
399in_delmulti(struct in_multi *inm)
400{
401	struct ifnet *ifp;
402
403	KASSERT(inm != NULL, ("%s: inm is NULL", __func__));
404	KASSERT(inm->inm_ifma != NULL, ("%s: no ifma", __func__));
405	ifp = inm->inm_ifma->ifma_ifp;
406
407	if (ifp != NULL) {
408		/*
409		 * Sanity check that netinet's notion of ifp is the
410		 * same as net's.
411		 */
412		KASSERT(inm->inm_ifp == ifp, ("%s: bad ifp", __func__));
413		IFF_LOCKGIANT(ifp);
414	}
415
416	IN_MULTI_LOCK();
417	in_delmulti_locked(inm);
418	IN_MULTI_UNLOCK();
419
420	if (ifp != NULL)
421		IFF_UNLOCKGIANT(ifp);
422}
423
424/*
425 * Delete a multicast address record, with locks held.
426 *
427 * It is OK to call this routine if the ifp went away.
428 * Assumes that caller holds the IN_MULTI lock, and that
429 * Giant was taken before other locks if required by the hardware.
430 */
431void
432in_delmulti_locked(struct in_multi *inm)
433{
434	struct ifmultiaddr *ifma;
435
436	IN_MULTI_LOCK_ASSERT();
437	KASSERT(inm->inm_refcount >= 1, ("%s: freeing freed inm", __func__));
438
439	if (--inm->inm_refcount == 0) {
440		igmp_leavegroup(inm);
441
442		ifma = inm->inm_ifma;
443#ifdef DIAGNOSTIC
444		if (bootverbose)
445			printf("%s: purging ifma %p\n", __func__, ifma);
446#endif
447		KASSERT(ifma->ifma_protospec == inm,
448		    ("%s: ifma_protospec != inm", __func__));
449		ifma->ifma_protospec = NULL;
450
451		LIST_REMOVE(inm, inm_link);
452		free(inm, M_IPMADDR);
453
454		if_delmulti_ifma(ifma);
455	}
456}
457
458/*
459 * Block or unblock an ASM/SSM multicast source on an inpcb.
460 */
461static int
462inp_change_source_filter(struct inpcb *inp, struct sockopt *sopt)
463{
464	struct group_source_req		 gsr;
465	sockunion_t			*gsa, *ssa;
466	struct ifnet			*ifp;
467	struct in_mfilter		*imf;
468	struct ip_moptions		*imo;
469	struct in_msource		*ims;
470	size_t				 idx;
471	int				 error;
472	int				 block;
473
474	ifp = NULL;
475	error = 0;
476	block = 0;
477
478	memset(&gsr, 0, sizeof(struct group_source_req));
479	gsa = (sockunion_t *)&gsr.gsr_group;
480	ssa = (sockunion_t *)&gsr.gsr_source;
481
482	switch (sopt->sopt_name) {
483	case IP_BLOCK_SOURCE:
484	case IP_UNBLOCK_SOURCE: {
485		struct ip_mreq_source	 mreqs;
486
487		error = sooptcopyin(sopt, &mreqs,
488		    sizeof(struct ip_mreq_source),
489		    sizeof(struct ip_mreq_source));
490		if (error)
491			return (error);
492
493		gsa->sin.sin_family = AF_INET;
494		gsa->sin.sin_len = sizeof(struct sockaddr_in);
495		gsa->sin.sin_addr = mreqs.imr_multiaddr;
496
497		ssa->sin.sin_family = AF_INET;
498		ssa->sin.sin_len = sizeof(struct sockaddr_in);
499		ssa->sin.sin_addr = mreqs.imr_sourceaddr;
500
501		if (mreqs.imr_interface.s_addr != INADDR_ANY)
502			INADDR_TO_IFP(mreqs.imr_interface, ifp);
503
504		if (sopt->sopt_name == IP_BLOCK_SOURCE)
505			block = 1;
506
507#ifdef DIAGNOSTIC
508		if (bootverbose) {
509			printf("%s: imr_interface = %s, ifp = %p\n",
510			    __func__, inet_ntoa(mreqs.imr_interface), ifp);
511		}
512#endif
513		break;
514	    }
515
516	case MCAST_BLOCK_SOURCE:
517	case MCAST_UNBLOCK_SOURCE:
518		error = sooptcopyin(sopt, &gsr,
519		    sizeof(struct group_source_req),
520		    sizeof(struct group_source_req));
521		if (error)
522			return (error);
523
524		if (gsa->sin.sin_family != AF_INET ||
525		    gsa->sin.sin_len != sizeof(struct sockaddr_in))
526			return (EINVAL);
527
528		if (ssa->sin.sin_family != AF_INET ||
529		    ssa->sin.sin_len != sizeof(struct sockaddr_in))
530			return (EINVAL);
531
532		if (gsr.gsr_interface == 0 || if_index < gsr.gsr_interface)
533			return (EADDRNOTAVAIL);
534
535		ifp = ifnet_byindex(gsr.gsr_interface);
536
537		if (sopt->sopt_name == MCAST_BLOCK_SOURCE)
538			block = 1;
539		break;
540
541	default:
542#ifdef DIAGNOSTIC
543		if (bootverbose) {
544			printf("%s: unknown sopt_name %d\n", __func__,
545			    sopt->sopt_name);
546		}
547#endif
548		return (EOPNOTSUPP);
549		break;
550	}
551
552	/* XXX INET6 */
553	if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr)))
554		return (EINVAL);
555
556	/*
557	 * Check if we are actually a member of this group.
558	 */
559	imo = inp_findmoptions(inp);
560	idx = imo_match_group(imo, ifp, &gsa->sa);
561	if (idx == -1 || imo->imo_mfilters == NULL) {
562		error = EADDRNOTAVAIL;
563		goto out_locked;
564	}
565
566	KASSERT(imo->imo_mfilters != NULL,
567	    ("%s: imo_mfilters not allocated", __func__));
568	imf = &imo->imo_mfilters[idx];
569
570	/*
571	 * SSM multicast truth table for block/unblock operations.
572	 *
573	 * Operation   Filter Mode  Entry exists?   Action
574	 *
575	 * block       exclude      no              add source to filter
576	 * unblock     include      no              add source to filter
577	 * block       include      no              EINVAL
578	 * unblock     exclude      no              EINVAL
579	 * block       exclude      yes             EADDRNOTAVAIL
580	 * unblock     include      yes             EADDRNOTAVAIL
581	 * block       include      yes             remove source from filter
582	 * unblock     exclude      yes             remove source from filter
583	 *
584	 * FreeBSD does not explicitly distinguish between ASM and SSM
585	 * mode sockets; all sockets are assumed to have a filter list.
586	 */
587#ifdef DIAGNOSTIC
588	if (bootverbose) {
589		printf("%s: imf_fmode is %s\n", __func__,
590		    imf->imf_fmode == MCAST_INCLUDE ? "include" : "exclude");
591	}
592#endif
593	ims = imo_match_source(imo, idx, &ssa->sa);
594	if (ims == NULL) {
595		if ((block == 1 && imf->imf_fmode == MCAST_EXCLUDE) ||
596		    (block == 0 && imf->imf_fmode == MCAST_INCLUDE)) {
597#ifdef DIAGNOSTIC
598			if (bootverbose) {
599				printf("%s: adding %s to filter list\n",
600				    __func__, inet_ntoa(ssa->sin.sin_addr));
601			}
602#endif
603			error = imo_join_source(imo, idx, ssa);
604		}
605		if ((block == 1 && imf->imf_fmode == MCAST_INCLUDE) ||
606		    (block == 0 && imf->imf_fmode == MCAST_EXCLUDE)) {
607			/*
608			 * If the socket is in inclusive mode:
609			 *  the source is already blocked as it has no entry.
610			 * If the socket is in exclusive mode:
611			 *  the source is already unblocked as it has no entry.
612			 */
613#ifdef DIAGNOSTIC
614			if (bootverbose) {
615				printf("%s: ims %p; %s already [un]blocked\n",
616				    __func__, ims,
617				    inet_ntoa(ssa->sin.sin_addr));
618			}
619#endif
620			error = EINVAL;
621		}
622	} else {
623		if ((block == 1 && imf->imf_fmode == MCAST_EXCLUDE) ||
624		    (block == 0 && imf->imf_fmode == MCAST_INCLUDE)) {
625			/*
626			 * If the socket is in exclusive mode:
627			 *  the source is already blocked as it has an entry.
628			 * If the socket is in inclusive mode:
629			 *  the source is already unblocked as it has an entry.
630			 */
631#ifdef DIAGNOSTIC
632			if (bootverbose) {
633				printf("%s: ims %p; %s already [un]blocked\n",
634				    __func__, ims,
635				    inet_ntoa(ssa->sin.sin_addr));
636			}
637#endif
638			error = EADDRNOTAVAIL;
639		}
640		if ((block == 1 && imf->imf_fmode == MCAST_INCLUDE) ||
641		    (block == 0 && imf->imf_fmode == MCAST_EXCLUDE)) {
642#ifdef DIAGNOSTIC
643			if (bootverbose) {
644				printf("%s: removing %s from filter list\n",
645				    __func__, inet_ntoa(ssa->sin.sin_addr));
646			}
647#endif
648			error = imo_leave_source(imo, idx, ssa);
649		}
650	}
651
652out_locked:
653	INP_UNLOCK(inp);
654	return (error);
655}
656
657/*
658 * Given an inpcb, return its multicast options structure pointer.  Accepts
659 * an unlocked inpcb pointer, but will return it locked.  May sleep.
660 */
661static struct ip_moptions *
662inp_findmoptions(struct inpcb *inp)
663{
664	struct ip_moptions	 *imo;
665	struct in_multi		**immp;
666	struct in_mfilter	 *imfp;
667	size_t			  idx;
668
669	INP_LOCK(inp);
670	if (inp->inp_moptions != NULL)
671		return (inp->inp_moptions);
672
673	INP_UNLOCK(inp);
674
675	imo = (struct ip_moptions *)malloc(sizeof(*imo), M_IPMOPTS,
676	    M_WAITOK);
677	immp = (struct in_multi **)malloc(sizeof(*immp) * IP_MIN_MEMBERSHIPS,
678	    M_IPMOPTS, M_WAITOK | M_ZERO);
679	imfp = (struct in_mfilter *)malloc(
680	    sizeof(struct in_mfilter) * IP_MIN_MEMBERSHIPS,
681	    M_IPMSOURCE, M_WAITOK);
682
683	imo->imo_multicast_ifp = NULL;
684	imo->imo_multicast_addr.s_addr = INADDR_ANY;
685	imo->imo_multicast_vif = -1;
686	imo->imo_multicast_ttl = IP_DEFAULT_MULTICAST_TTL;
687	imo->imo_multicast_loop = IP_DEFAULT_MULTICAST_LOOP;
688	imo->imo_num_memberships = 0;
689	imo->imo_max_memberships = IP_MIN_MEMBERSHIPS;
690	imo->imo_membership = immp;
691
692	/* Initialize per-group source filters. */
693	for (idx = 0; idx < IP_MIN_MEMBERSHIPS; idx++) {
694		imfp[idx].imf_fmode = MCAST_EXCLUDE;
695		imfp[idx].imf_nsources = 0;
696		TAILQ_INIT(&imfp[idx].imf_sources);
697	}
698	imo->imo_mfilters = imfp;
699
700	INP_LOCK(inp);
701	if (inp->inp_moptions != NULL) {
702		free(imfp, M_IPMSOURCE);
703		free(immp, M_IPMOPTS);
704		free(imo, M_IPMOPTS);
705		return (inp->inp_moptions);
706	}
707	inp->inp_moptions = imo;
708	return (imo);
709}
710
711/*
712 * Discard the IP multicast options (and source filters).
713 */
714void
715inp_freemoptions(struct ip_moptions *imo)
716{
717	struct in_mfilter	*imf;
718	struct in_msource	*ims, *tims;
719	size_t			 idx, nmships;
720
721	KASSERT(imo != NULL, ("%s: ip_moptions is NULL", __func__));
722
723	nmships = imo->imo_num_memberships;
724	for (idx = 0; idx < nmships; ++idx) {
725		in_delmulti(imo->imo_membership[idx]);
726
727		if (imo->imo_mfilters != NULL) {
728			imf = &imo->imo_mfilters[idx];
729			TAILQ_FOREACH_SAFE(ims, &imf->imf_sources,
730			    ims_next, tims) {
731				TAILQ_REMOVE(&imf->imf_sources, ims, ims_next);
732				FREE(ims, M_IPMSOURCE);
733				imf->imf_nsources--;
734			}
735			KASSERT(imf->imf_nsources == 0,
736			    ("%s: did not free all imf_nsources", __func__));
737		}
738	}
739
740	if (imo->imo_mfilters != NULL)
741		free(imo->imo_mfilters, M_IPMSOURCE);
742	free(imo->imo_membership, M_IPMOPTS);
743	free(imo, M_IPMOPTS);
744}
745
746/*
747 * Atomically get source filters on a socket for an IPv4 multicast group.
748 * Called with INP lock held; returns with lock released.
749 */
750static int
751inp_get_source_filters(struct inpcb *inp, struct sockopt *sopt)
752{
753	struct __msfilterreq	 msfr;
754	sockunion_t		*gsa;
755	struct ifnet		*ifp;
756	struct ip_moptions	*imo;
757	struct in_mfilter	*imf;
758	struct in_msource	*ims;
759	struct sockaddr_storage	*ptss;
760	struct sockaddr_storage	*tss;
761	int			 error;
762	size_t			 idx;
763
764	INP_LOCK_ASSERT(inp);
765
766	imo = inp->inp_moptions;
767	KASSERT(imo != NULL, ("%s: null ip_moptions", __func__));
768
769	INP_UNLOCK(inp);
770
771	error = sooptcopyin(sopt, &msfr, sizeof(struct __msfilterreq),
772	    sizeof(struct __msfilterreq));
773	if (error)
774		return (error);
775
776	if (msfr.msfr_ifindex == 0 || if_index < msfr.msfr_ifindex)
777		return (EINVAL);
778
779	ifp = ifnet_byindex(msfr.msfr_ifindex);
780	if (ifp == NULL)
781		return (EINVAL);
782
783	INP_LOCK(inp);
784
785	/*
786	 * Lookup group on the socket.
787	 */
788	gsa = (sockunion_t *)&msfr.msfr_group;
789	idx = imo_match_group(imo, ifp, &gsa->sa);
790	if (idx == -1 || imo->imo_mfilters == NULL) {
791		INP_UNLOCK(inp);
792		return (EADDRNOTAVAIL);
793	}
794
795	imf = &imo->imo_mfilters[idx];
796	msfr.msfr_fmode = imf->imf_fmode;
797	msfr.msfr_nsrcs = imf->imf_nsources;
798
799	/*
800	 * If the user specified a buffer, copy out the source filter
801	 * entries to userland gracefully.
802	 * msfr.msfr_nsrcs is always set to the total number of filter
803	 * entries which the kernel currently has for this group.
804	 */
805	tss = NULL;
806	if (msfr.msfr_srcs != NULL && msfr.msfr_nsrcs > 0) {
807		/*
808		 * Make a copy of the source vector so that we do not
809		 * thrash the inpcb lock whilst copying it out.
810		 * We only copy out the number of entries which userland
811		 * has asked for, but we always tell userland how big the
812		 * buffer really needs to be.
813		 */
814		MALLOC(tss, struct sockaddr_storage *,
815		    sizeof(struct sockaddr_storage) * msfr.msfr_nsrcs,
816		    M_TEMP, M_NOWAIT);
817		if (tss == NULL) {
818			error = ENOBUFS;
819		} else {
820			ptss = tss;
821			TAILQ_FOREACH(ims, &imf->imf_sources, ims_next) {
822				memcpy(ptss++, &ims->ims_addr,
823				    sizeof(struct sockaddr_storage));
824			}
825		}
826	}
827
828	INP_UNLOCK(inp);
829
830	if (tss != NULL) {
831		error = copyout(tss, msfr.msfr_srcs,
832		    sizeof(struct sockaddr_storage) * msfr.msfr_nsrcs);
833		FREE(tss, M_TEMP);
834	}
835
836	if (error)
837		return (error);
838
839	error = sooptcopyout(sopt, &msfr, sizeof(struct __msfilterreq));
840
841	return (error);
842}
843
844/*
845 * Return the IP multicast options in response to user getsockopt().
846 */
847int
848inp_getmoptions(struct inpcb *inp, struct sockopt *sopt)
849{
850	struct ip_mreqn		 mreqn;
851	struct ip_moptions	*imo;
852	struct ifnet		*ifp;
853	struct in_ifaddr	*ia;
854	int			 error, optval;
855	u_char			 coptval;
856
857	INP_LOCK(inp);
858	imo = inp->inp_moptions;
859
860	error = 0;
861	switch (sopt->sopt_name) {
862	case IP_MULTICAST_VIF:
863		if (imo != NULL)
864			optval = imo->imo_multicast_vif;
865		else
866			optval = -1;
867		INP_UNLOCK(inp);
868		error = sooptcopyout(sopt, &optval, sizeof(int));
869		break;
870
871	case IP_MULTICAST_IF:
872		memset(&mreqn, 0, sizeof(struct ip_mreqn));
873		if (imo != NULL) {
874			ifp = imo->imo_multicast_ifp;
875			if (imo->imo_multicast_addr.s_addr != INADDR_ANY) {
876				mreqn.imr_address = imo->imo_multicast_addr;
877			} else if (ifp != NULL) {
878				mreqn.imr_ifindex = ifp->if_index;
879				IFP_TO_IA(ifp, ia);
880				if (ia != NULL) {
881					mreqn.imr_address =
882					    IA_SIN(ia)->sin_addr;
883				}
884			}
885		}
886		INP_UNLOCK(inp);
887		if (sopt->sopt_valsize == sizeof(struct ip_mreqn)) {
888			error = sooptcopyout(sopt, &mreqn,
889			    sizeof(struct ip_mreqn));
890		} else {
891			error = sooptcopyout(sopt, &mreqn.imr_address,
892			    sizeof(struct in_addr));
893		}
894		break;
895
896	case IP_MULTICAST_TTL:
897		if (imo == 0)
898			optval = coptval = IP_DEFAULT_MULTICAST_TTL;
899		else
900			optval = coptval = imo->imo_multicast_ttl;
901		INP_UNLOCK(inp);
902		if (sopt->sopt_valsize == sizeof(u_char))
903			error = sooptcopyout(sopt, &coptval, sizeof(u_char));
904		else
905			error = sooptcopyout(sopt, &optval, sizeof(int));
906		break;
907
908	case IP_MULTICAST_LOOP:
909		if (imo == 0)
910			optval = coptval = IP_DEFAULT_MULTICAST_LOOP;
911		else
912			optval = coptval = imo->imo_multicast_loop;
913		INP_UNLOCK(inp);
914		if (sopt->sopt_valsize == sizeof(u_char))
915			error = sooptcopyout(sopt, &coptval, sizeof(u_char));
916		else
917			error = sooptcopyout(sopt, &optval, sizeof(int));
918		break;
919
920	case IP_MSFILTER:
921		if (imo == NULL) {
922			error = EADDRNOTAVAIL;
923			INP_UNLOCK(inp);
924		} else {
925			error = inp_get_source_filters(inp, sopt);
926		}
927		break;
928
929	default:
930		INP_UNLOCK(inp);
931		error = ENOPROTOOPT;
932		break;
933	}
934
935	INP_UNLOCK_ASSERT(inp);
936
937	return (error);
938}
939
940/*
941 * Join an IPv4 multicast group, possibly with a source.
942 */
943static int
944inp_join_group(struct inpcb *inp, struct sockopt *sopt)
945{
946	struct group_source_req		 gsr;
947	sockunion_t			*gsa, *ssa;
948	struct ifnet			*ifp;
949	struct in_mfilter		*imf;
950	struct ip_moptions		*imo;
951	struct in_multi			*inm;
952	size_t				 idx;
953	int				 error;
954
955	ifp = NULL;
956	error = 0;
957
958	memset(&gsr, 0, sizeof(struct group_source_req));
959	gsa = (sockunion_t *)&gsr.gsr_group;
960	gsa->ss.ss_family = AF_UNSPEC;
961	ssa = (sockunion_t *)&gsr.gsr_source;
962	ssa->ss.ss_family = AF_UNSPEC;
963
964	switch (sopt->sopt_name) {
965	case IP_ADD_MEMBERSHIP:
966	case IP_ADD_SOURCE_MEMBERSHIP: {
967		struct ip_mreq_source	 mreqs;
968
969		if (sopt->sopt_name == IP_ADD_MEMBERSHIP) {
970			error = sooptcopyin(sopt, &mreqs,
971			    sizeof(struct ip_mreq),
972			    sizeof(struct ip_mreq));
973			/*
974			 * Do argument switcharoo from ip_mreq into
975			 * ip_mreq_source to avoid using two instances.
976			 */
977			mreqs.imr_interface = mreqs.imr_sourceaddr;
978			mreqs.imr_sourceaddr.s_addr = INADDR_ANY;
979		} else if (sopt->sopt_name == IP_ADD_SOURCE_MEMBERSHIP) {
980			error = sooptcopyin(sopt, &mreqs,
981			    sizeof(struct ip_mreq_source),
982			    sizeof(struct ip_mreq_source));
983		}
984		if (error)
985			return (error);
986
987		gsa->sin.sin_family = AF_INET;
988		gsa->sin.sin_len = sizeof(struct sockaddr_in);
989		gsa->sin.sin_addr = mreqs.imr_multiaddr;
990
991		if (sopt->sopt_name == IP_ADD_SOURCE_MEMBERSHIP) {
992			ssa->sin.sin_family = AF_INET;
993			ssa->sin.sin_len = sizeof(struct sockaddr_in);
994			ssa->sin.sin_addr = mreqs.imr_sourceaddr;
995		}
996
997		/*
998		 * Obtain ifp. If no interface address was provided,
999		 * use the interface of the route to the given multicast
1000		 * address (usually this is the default route).
1001		 */
1002		if (mreqs.imr_interface.s_addr != INADDR_ANY) {
1003			INADDR_TO_IFP(mreqs.imr_interface, ifp);
1004		} else {
1005			struct route ro;
1006
1007			ro.ro_rt = NULL;
1008			*(struct sockaddr_in *)&ro.ro_dst = gsa->sin;
1009			rtalloc_ign(&ro, RTF_CLONING);
1010			if (ro.ro_rt == NULL) {
1011#ifdef DIAGNOSTIC
1012				printf("%s: no route to %s\n", __func__,
1013				    inet_ntoa(gsa->sin.sin_addr));
1014#endif
1015				return (EADDRNOTAVAIL);
1016			}
1017			ifp = ro.ro_rt->rt_ifp;
1018			KASSERT(ifp != NULL, ("%s: null ifp", __func__));
1019			RTFREE(ro.ro_rt);
1020		}
1021#ifdef DIAGNOSTIC
1022		if (bootverbose) {
1023			printf("%s: imr_interface = %s, ifp = %p\n",
1024			    __func__, inet_ntoa(mreqs.imr_interface), ifp);
1025		}
1026#endif
1027		break;
1028	}
1029
1030	case MCAST_JOIN_GROUP:
1031	case MCAST_JOIN_SOURCE_GROUP:
1032		if (sopt->sopt_name == MCAST_JOIN_GROUP) {
1033			error = sooptcopyin(sopt, &gsr,
1034			    sizeof(struct group_req),
1035			    sizeof(struct group_req));
1036		} else if (sopt->sopt_name == MCAST_JOIN_SOURCE_GROUP) {
1037			error = sooptcopyin(sopt, &gsr,
1038			    sizeof(struct group_source_req),
1039			    sizeof(struct group_source_req));
1040		}
1041		if (error)
1042			return (error);
1043
1044		if (gsa->sin.sin_family != AF_INET ||
1045		    gsa->sin.sin_len != sizeof(struct sockaddr_in))
1046			return (EINVAL);
1047
1048		/*
1049		 * Overwrite the port field if present, as the sockaddr
1050		 * being copied in may be matched with a binary comparison.
1051		 * XXX INET6
1052		 */
1053		gsa->sin.sin_port = 0;
1054		if (sopt->sopt_name == MCAST_JOIN_SOURCE_GROUP) {
1055			if (ssa->sin.sin_family != AF_INET ||
1056			    ssa->sin.sin_len != sizeof(struct sockaddr_in))
1057				return (EINVAL);
1058			ssa->sin.sin_port = 0;
1059		}
1060
1061		/*
1062		 * Obtain the ifp.
1063		 */
1064		if (gsr.gsr_interface == 0 || if_index < gsr.gsr_interface)
1065			return (EADDRNOTAVAIL);
1066		ifp = ifnet_byindex(gsr.gsr_interface);
1067
1068		break;
1069
1070	default:
1071#ifdef DIAGNOSTIC
1072		if (bootverbose) {
1073			printf("%s: unknown sopt_name %d\n", __func__,
1074			    sopt->sopt_name);
1075		}
1076#endif
1077		return (EOPNOTSUPP);
1078		break;
1079	}
1080
1081	if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr)))
1082		return (EINVAL);
1083
1084	if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0)
1085		return (EADDRNOTAVAIL);
1086
1087	/*
1088	 * Check if we already hold membership of this group for this inpcb.
1089	 * If so, we do not need to perform the initial join.
1090	 */
1091	imo = inp_findmoptions(inp);
1092	idx = imo_match_group(imo, ifp, &gsa->sa);
1093	if (idx != -1) {
1094		if (ssa->ss.ss_family != AF_UNSPEC) {
1095			/*
1096			 * Attempting to join an ASM group (when already
1097			 * an ASM or SSM member) is an error.
1098			 */
1099			error = EADDRNOTAVAIL;
1100		} else {
1101			imf = &imo->imo_mfilters[idx];
1102			if (imf->imf_nsources == 0) {
1103				/*
1104				 * Attempting to join an SSM group (when
1105				 * already an ASM member) is an error.
1106				 */
1107				error = EINVAL;
1108			} else {
1109				/*
1110				 * Attempting to join an SSM group (when
1111				 * already an SSM member) means "add this
1112				 * source to the inclusive filter list".
1113				 */
1114				error = imo_join_source(imo, idx, ssa);
1115			}
1116		}
1117		goto out_locked;
1118	}
1119
1120	/*
1121	 * Call imo_grow() to reallocate the membership and source filter
1122	 * vectors if they are full. If the size would exceed the hard limit,
1123	 * then we know we've really run out of entries. We keep the INP
1124	 * lock held to avoid introducing a race condition.
1125	 */
1126	if (imo->imo_num_memberships == imo->imo_max_memberships) {
1127		error = imo_grow(imo);
1128		if (error)
1129			goto out_locked;
1130	}
1131
1132	/*
1133	 * So far, so good: perform the layer 3 join, layer 2 join,
1134	 * and make an IGMP announcement if needed.
1135	 */
1136	inm = in_addmulti(&gsa->sin.sin_addr, ifp);
1137	if (inm == NULL) {
1138		error = ENOBUFS;
1139		goto out_locked;
1140	}
1141	idx = imo->imo_num_memberships;
1142	imo->imo_membership[idx] = inm;
1143	imo->imo_num_memberships++;
1144
1145	KASSERT(imo->imo_mfilters != NULL,
1146	    ("%s: imf_mfilters vector was not allocated", __func__));
1147	imf = &imo->imo_mfilters[idx];
1148	KASSERT(TAILQ_EMPTY(&imf->imf_sources),
1149	    ("%s: imf_sources not empty", __func__));
1150
1151	/*
1152	 * If this is a new SSM group join (i.e. a source was specified
1153	 * with this group), add this source to the filter list.
1154	 */
1155	if (ssa->ss.ss_family != AF_UNSPEC) {
1156		/*
1157		 * An initial SSM join implies that this socket's membership
1158		 * of the multicast group is now in inclusive mode.
1159		 */
1160		imf->imf_fmode = MCAST_INCLUDE;
1161
1162		error = imo_join_source(imo, idx, ssa);
1163		if (error) {
1164			/*
1165			 * Drop inp lock before calling in_delmulti(),
1166			 * to prevent a lock order reversal.
1167			 */
1168			--imo->imo_num_memberships;
1169			INP_UNLOCK(inp);
1170			in_delmulti(inm);
1171			return (error);
1172		}
1173	}
1174
1175out_locked:
1176	INP_UNLOCK(inp);
1177	return (error);
1178}
1179
1180/*
1181 * Leave an IPv4 multicast group on an inpcb, possibly with a source.
1182 */
1183static int
1184inp_leave_group(struct inpcb *inp, struct sockopt *sopt)
1185{
1186	struct group_source_req		 gsr;
1187	struct ip_mreq_source		 mreqs;
1188	sockunion_t			*gsa, *ssa;
1189	struct ifnet			*ifp;
1190	struct in_mfilter		*imf;
1191	struct ip_moptions		*imo;
1192	struct in_msource		*ims, *tims;
1193	struct in_multi			*inm;
1194	size_t				 idx;
1195	int				 error;
1196
1197	ifp = NULL;
1198	error = 0;
1199
1200	memset(&gsr, 0, sizeof(struct group_source_req));
1201	gsa = (sockunion_t *)&gsr.gsr_group;
1202	gsa->ss.ss_family = AF_UNSPEC;
1203	ssa = (sockunion_t *)&gsr.gsr_source;
1204	ssa->ss.ss_family = AF_UNSPEC;
1205
1206	switch (sopt->sopt_name) {
1207	case IP_DROP_MEMBERSHIP:
1208	case IP_DROP_SOURCE_MEMBERSHIP:
1209		if (sopt->sopt_name == IP_DROP_MEMBERSHIP) {
1210			error = sooptcopyin(sopt, &mreqs,
1211			    sizeof(struct ip_mreq),
1212			    sizeof(struct ip_mreq));
1213			/*
1214			 * Swap interface and sourceaddr arguments,
1215			 * as ip_mreq and ip_mreq_source are laid
1216			 * out differently.
1217			 */
1218			mreqs.imr_interface = mreqs.imr_sourceaddr;
1219			mreqs.imr_sourceaddr.s_addr = INADDR_ANY;
1220		} else if (sopt->sopt_name == IP_DROP_SOURCE_MEMBERSHIP) {
1221			error = sooptcopyin(sopt, &mreqs,
1222			    sizeof(struct ip_mreq_source),
1223			    sizeof(struct ip_mreq_source));
1224		}
1225		if (error)
1226			return (error);
1227
1228		gsa->sin.sin_family = AF_INET;
1229		gsa->sin.sin_len = sizeof(struct sockaddr_in);
1230		gsa->sin.sin_addr = mreqs.imr_multiaddr;
1231
1232		if (sopt->sopt_name == IP_DROP_SOURCE_MEMBERSHIP) {
1233			ssa->sin.sin_family = AF_INET;
1234			ssa->sin.sin_len = sizeof(struct sockaddr_in);
1235			ssa->sin.sin_addr = mreqs.imr_sourceaddr;
1236		}
1237
1238		if (gsa->sin.sin_addr.s_addr != INADDR_ANY)
1239			INADDR_TO_IFP(mreqs.imr_interface, ifp);
1240
1241#ifdef DIAGNOSTIC
1242		if (bootverbose) {
1243			printf("%s: imr_interface = %s, ifp = %p\n",
1244			    __func__, inet_ntoa(mreqs.imr_interface), ifp);
1245		}
1246#endif
1247		break;
1248
1249	case MCAST_LEAVE_GROUP:
1250	case MCAST_LEAVE_SOURCE_GROUP:
1251		if (sopt->sopt_name == MCAST_LEAVE_GROUP) {
1252			error = sooptcopyin(sopt, &gsr,
1253			    sizeof(struct group_req),
1254			    sizeof(struct group_req));
1255		} else if (sopt->sopt_name == MCAST_LEAVE_SOURCE_GROUP) {
1256			error = sooptcopyin(sopt, &gsr,
1257			    sizeof(struct group_source_req),
1258			    sizeof(struct group_source_req));
1259		}
1260		if (error)
1261			return (error);
1262
1263		if (gsa->sin.sin_family != AF_INET ||
1264		    gsa->sin.sin_len != sizeof(struct sockaddr_in))
1265			return (EINVAL);
1266
1267		if (sopt->sopt_name == MCAST_LEAVE_SOURCE_GROUP) {
1268			if (ssa->sin.sin_family != AF_INET ||
1269			    ssa->sin.sin_len != sizeof(struct sockaddr_in))
1270				return (EINVAL);
1271		}
1272
1273		if (gsr.gsr_interface == 0 || if_index < gsr.gsr_interface)
1274			return (EADDRNOTAVAIL);
1275
1276		ifp = ifnet_byindex(gsr.gsr_interface);
1277		break;
1278
1279	default:
1280#ifdef DIAGNOSTIC
1281		if (bootverbose) {
1282			printf("%s: unknown sopt_name %d\n", __func__,
1283			    sopt->sopt_name);
1284		}
1285#endif
1286		return (EOPNOTSUPP);
1287		break;
1288	}
1289
1290	if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr)))
1291		return (EINVAL);
1292
1293	/*
1294	 * Find the membership in the membership array.
1295	 */
1296	imo = inp_findmoptions(inp);
1297	idx = imo_match_group(imo, ifp, &gsa->sa);
1298	if (idx == -1) {
1299		error = EADDRNOTAVAIL;
1300		goto out_locked;
1301	}
1302	imf = &imo->imo_mfilters[idx];
1303
1304	/*
1305	 * If we were instructed only to leave a given source, do so.
1306	 */
1307	if (ssa->ss.ss_family != AF_UNSPEC) {
1308		if (imf->imf_nsources == 0 ||
1309		    imf->imf_fmode == MCAST_EXCLUDE) {
1310			/*
1311			 * Attempting to SSM leave an ASM group
1312			 * is an error; should use *_BLOCK_SOURCE instead.
1313			 * Attempting to SSM leave a source in a group when
1314			 * the socket is in 'exclude mode' is also an error.
1315			 */
1316			error = EINVAL;
1317		} else {
1318			error = imo_leave_source(imo, idx, ssa);
1319		}
1320		/*
1321		 * If an error occurred, or this source is not the last
1322		 * source in the group, do not leave the whole group.
1323		 */
1324		if (error || imf->imf_nsources > 0)
1325			goto out_locked;
1326	}
1327
1328	/*
1329	 * Give up the multicast address record to which the membership points.
1330	 */
1331	inm = imo->imo_membership[idx];
1332	in_delmulti(inm);
1333
1334	/*
1335	 * Free any source filters for this group if they exist.
1336	 * Revert inpcb to the default MCAST_EXCLUDE state.
1337	 */
1338	if (imo->imo_mfilters != NULL) {
1339		TAILQ_FOREACH_SAFE(ims, &imf->imf_sources, ims_next, tims) {
1340			TAILQ_REMOVE(&imf->imf_sources, ims, ims_next);
1341			FREE(ims, M_IPMSOURCE);
1342			imf->imf_nsources--;
1343		}
1344		KASSERT(imf->imf_nsources == 0,
1345		    ("%s: imf_nsources not 0", __func__));
1346		KASSERT(TAILQ_EMPTY(&imf->imf_sources),
1347		    ("%s: imf_sources not empty", __func__));
1348		imf->imf_fmode = MCAST_EXCLUDE;
1349	}
1350
1351	/*
1352	 * Remove the gap in the membership array.
1353	 */
1354	for (++idx; idx < imo->imo_num_memberships; ++idx)
1355		imo->imo_membership[idx-1] = imo->imo_membership[idx];
1356	imo->imo_num_memberships--;
1357
1358out_locked:
1359	INP_UNLOCK(inp);
1360	return (error);
1361}
1362
1363/*
1364 * Select the interface for transmitting IPv4 multicast datagrams.
1365 *
1366 * Either an instance of struct in_addr or an instance of struct ip_mreqn
1367 * may be passed to this socket option. An address of INADDR_ANY or an
1368 * interface index of 0 is used to remove a previous selection.
1369 * When no interface is selected, one is chosen for every send.
1370 */
1371static int
1372inp_set_multicast_if(struct inpcb *inp, struct sockopt *sopt)
1373{
1374	struct in_addr		 addr;
1375	struct ip_mreqn		 mreqn;
1376	struct ifnet		*ifp;
1377	struct ip_moptions	*imo;
1378	int			 error;
1379
1380	if (sopt->sopt_valsize == sizeof(struct ip_mreqn)) {
1381		/*
1382		 * An interface index was specified using the
1383		 * Linux-derived ip_mreqn structure.
1384		 */
1385		error = sooptcopyin(sopt, &mreqn, sizeof(struct ip_mreqn),
1386		    sizeof(struct ip_mreqn));
1387		if (error)
1388			return (error);
1389
1390		if (mreqn.imr_ifindex < 0 || if_index < mreqn.imr_ifindex)
1391			return (EINVAL);
1392
1393		if (mreqn.imr_ifindex == 0) {
1394			ifp = NULL;
1395		} else {
1396			ifp = ifnet_byindex(mreqn.imr_ifindex);
1397			if (ifp == NULL)
1398				return (EADDRNOTAVAIL);
1399		}
1400	} else {
1401		/*
1402		 * An interface was specified by IPv4 address.
1403		 * This is the traditional BSD usage.
1404		 */
1405		error = sooptcopyin(sopt, &addr, sizeof(struct in_addr),
1406		    sizeof(struct in_addr));
1407		if (error)
1408			return (error);
1409		if (addr.s_addr == INADDR_ANY) {
1410			ifp = NULL;
1411		} else {
1412			INADDR_TO_IFP(addr, ifp);
1413			if (ifp == NULL)
1414				return (EADDRNOTAVAIL);
1415		}
1416#ifdef DIAGNOSTIC
1417		if (bootverbose) {
1418			printf("%s: ifp = %p, addr = %s\n",
1419			    __func__, ifp, inet_ntoa(addr)); /* XXX INET6 */
1420		}
1421#endif
1422	}
1423
1424	/* Reject interfaces which do not support multicast. */
1425	if (ifp != NULL && (ifp->if_flags & IFF_MULTICAST) == 0)
1426		return (EOPNOTSUPP);
1427
1428	imo = inp_findmoptions(inp);
1429	imo->imo_multicast_ifp = ifp;
1430	imo->imo_multicast_addr.s_addr = INADDR_ANY;
1431	INP_UNLOCK(inp);
1432
1433	return (0);
1434}
1435
1436/*
1437 * Atomically set source filters on a socket for an IPv4 multicast group.
1438 */
1439static int
1440inp_set_source_filters(struct inpcb *inp, struct sockopt *sopt)
1441{
1442	struct __msfilterreq	 msfr;
1443	sockunion_t		*gsa;
1444	struct ifnet		*ifp;
1445	struct in_mfilter	*imf;
1446	struct ip_moptions	*imo;
1447	struct in_msource	*ims, *tims;
1448	size_t			 idx;
1449	int			 error;
1450
1451	error = sooptcopyin(sopt, &msfr, sizeof(struct __msfilterreq),
1452	    sizeof(struct __msfilterreq));
1453	if (error)
1454		return (error);
1455
1456	if (msfr.msfr_nsrcs > IP_MAX_SOURCE_FILTER ||
1457	    (msfr.msfr_fmode != MCAST_EXCLUDE &&
1458	     msfr.msfr_fmode != MCAST_INCLUDE))
1459		return (EINVAL);
1460
1461	if (msfr.msfr_group.ss_family != AF_INET ||
1462	    msfr.msfr_group.ss_len != sizeof(struct sockaddr_in))
1463		return (EINVAL);
1464
1465	gsa = (sockunion_t *)&msfr.msfr_group;
1466	if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr)))
1467		return (EINVAL);
1468
1469	gsa->sin.sin_port = 0;	/* ignore port */
1470
1471	if (msfr.msfr_ifindex == 0 || if_index < msfr.msfr_ifindex)
1472		return (EADDRNOTAVAIL);
1473
1474	ifp = ifnet_byindex(msfr.msfr_ifindex);
1475	if (ifp == NULL)
1476		return (EADDRNOTAVAIL);
1477
1478	/*
1479	 * Take the INP lock.
1480	 * Check if this socket is a member of this group.
1481	 */
1482	imo = inp_findmoptions(inp);
1483	idx = imo_match_group(imo, ifp, &gsa->sa);
1484	if (idx == -1 || imo->imo_mfilters == NULL) {
1485		error = EADDRNOTAVAIL;
1486		goto out_locked;
1487	}
1488	imf = &imo->imo_mfilters[idx];
1489
1490#ifdef DIAGNOSTIC
1491	if (bootverbose)
1492		printf("%s: clearing source list\n", __func__);
1493#endif
1494
1495	/*
1496	 * Remove any existing source filters.
1497	 */
1498	TAILQ_FOREACH_SAFE(ims, &imf->imf_sources, ims_next, tims) {
1499		TAILQ_REMOVE(&imf->imf_sources, ims, ims_next);
1500		FREE(ims, M_IPMSOURCE);
1501		imf->imf_nsources--;
1502	}
1503	KASSERT(imf->imf_nsources == 0,
1504	    ("%s: source list not cleared", __func__));
1505
1506	/*
1507	 * Apply any new source filters, if present.
1508	 */
1509	if (msfr.msfr_nsrcs > 0) {
1510		struct in_msource	**pnims;
1511		struct in_msource	*nims;
1512		struct sockaddr_storage	*kss;
1513		struct sockaddr_storage	*pkss;
1514		sockunion_t		*psu;
1515		int			 i, j;
1516
1517		/*
1518		 * Drop the inp lock so we may sleep if we need to
1519		 * in order to satisfy a malloc request.
1520		 * We will re-take it before changing socket state.
1521		 */
1522		INP_UNLOCK(inp);
1523#ifdef DIAGNOSTIC
1524		if (bootverbose) {
1525			printf("%s: loading %lu source list entries\n",
1526			    __func__, (unsigned long)msfr.msfr_nsrcs);
1527		}
1528#endif
1529		/*
1530		 * Make a copy of the user-space source vector so
1531		 * that we may copy them with a single copyin. This
1532		 * allows us to deal with page faults up-front.
1533		 */
1534		MALLOC(kss, struct sockaddr_storage *,
1535		    sizeof(struct sockaddr_storage) * msfr.msfr_nsrcs,
1536		    M_TEMP, M_WAITOK);
1537		error = copyin(msfr.msfr_srcs, kss,
1538		    sizeof(struct sockaddr_storage) * msfr.msfr_nsrcs);
1539		if (error) {
1540			FREE(kss, M_TEMP);
1541			return (error);
1542		}
1543
1544		/*
1545		 * Perform argument checking on every sockaddr_storage
1546		 * structure in the vector provided to us. Overwrite
1547		 * fields which should not apply to source entries.
1548		 * TODO: Check for duplicate sources on this pass.
1549		 */
1550		psu = (sockunion_t *)kss;
1551		for (i = 0; i < msfr.msfr_nsrcs; i++, psu++) {
1552			switch (psu->ss.ss_family) {
1553			case AF_INET:
1554				if (psu->sin.sin_len !=
1555				    sizeof(struct sockaddr_in)) {
1556					error = EINVAL;
1557				} else {
1558					psu->sin.sin_port = 0;
1559				}
1560				break;
1561#ifdef notyet
1562			case AF_INET6;
1563				if (psu->sin6.sin6_len !=
1564				    sizeof(struct sockaddr_in6)) {
1565					error = EINVAL;
1566				} else {
1567					psu->sin6.sin6_port = 0;
1568					psu->sin6.sin6_flowinfo = 0;
1569				}
1570				break;
1571#endif
1572			default:
1573				error = EAFNOSUPPORT;
1574				break;
1575			}
1576			if (error)
1577				break;
1578		}
1579		if (error) {
1580			FREE(kss, M_TEMP);
1581			return (error);
1582		}
1583
1584		/*
1585		 * Allocate a block to track all the in_msource
1586		 * entries we are about to allocate, in case we
1587		 * abruptly need to free them.
1588		 */
1589		MALLOC(pnims, struct in_msource **,
1590		    sizeof(struct in_msource *) * msfr.msfr_nsrcs,
1591		    M_TEMP, M_WAITOK | M_ZERO);
1592
1593		/*
1594		 * Allocate up to nsrcs individual chunks.
1595		 * If we encounter an error, backtrack out of
1596		 * all allocations cleanly; updates must be atomic.
1597		 */
1598		pkss = kss;
1599		nims = NULL;
1600		for (i = 0; i < msfr.msfr_nsrcs; i++, pkss++) {
1601			MALLOC(nims, struct in_msource *,
1602			    sizeof(struct in_msource) * msfr.msfr_nsrcs,
1603			    M_IPMSOURCE, M_WAITOK | M_ZERO);
1604			pnims[i] = nims;
1605		}
1606		if (i < msfr.msfr_nsrcs) {
1607			for (j = 0; j < i; j++) {
1608				if (pnims[j] != NULL)
1609					FREE(pnims[j], M_IPMSOURCE);
1610			}
1611			FREE(pnims, M_TEMP);
1612			FREE(kss, M_TEMP);
1613			return (ENOBUFS);
1614		}
1615
1616		INP_UNLOCK_ASSERT(inp);
1617
1618		/*
1619		 * Finally, apply the filters to the socket.
1620		 * Re-take the inp lock; we are changing socket state.
1621		 */
1622		pkss = kss;
1623		INP_LOCK(inp);
1624		for (i = 0; i < msfr.msfr_nsrcs; i++, pkss++) {
1625			memcpy(&(pnims[i]->ims_addr), pkss,
1626			    sizeof(struct sockaddr_storage));
1627			TAILQ_INSERT_TAIL(&imf->imf_sources, pnims[i],
1628			    ims_next);
1629			imf->imf_nsources++;
1630		}
1631		FREE(pnims, M_TEMP);
1632		FREE(kss, M_TEMP);
1633	}
1634
1635	/*
1636	 * Update the filter mode on the socket before releasing the inpcb.
1637	 */
1638	INP_LOCK_ASSERT(inp);
1639	imf->imf_fmode = msfr.msfr_fmode;
1640
1641out_locked:
1642	INP_UNLOCK(inp);
1643	return (error);
1644}
1645
1646/*
1647 * Set the IP multicast options in response to user setsockopt().
1648 *
1649 * Many of the socket options handled in this function duplicate the
1650 * functionality of socket options in the regular unicast API. However,
1651 * it is not possible to merge the duplicate code, because the idempotence
1652 * of the IPv4 multicast part of the BSD Sockets API must be preserved;
1653 * the effects of these options must be treated as separate and distinct.
1654 */
1655int
1656inp_setmoptions(struct inpcb *inp, struct sockopt *sopt)
1657{
1658	struct ip_moptions	*imo;
1659	int			 error;
1660
1661	error = 0;
1662
1663	switch (sopt->sopt_name) {
1664	case IP_MULTICAST_VIF: {
1665		int vifi;
1666		/*
1667		 * Select a multicast VIF for transmission.
1668		 * Only useful if multicast forwarding is active.
1669		 */
1670		if (legal_vif_num == NULL) {
1671			error = EOPNOTSUPP;
1672			break;
1673		}
1674		error = sooptcopyin(sopt, &vifi, sizeof(int), sizeof(int));
1675		if (error)
1676			break;
1677		if (!legal_vif_num(vifi) && (vifi != -1)) {
1678			error = EINVAL;
1679			break;
1680		}
1681		imo = inp_findmoptions(inp);
1682		imo->imo_multicast_vif = vifi;
1683		INP_UNLOCK(inp);
1684		break;
1685	}
1686
1687	case IP_MULTICAST_IF:
1688		error = inp_set_multicast_if(inp, sopt);
1689		break;
1690
1691	case IP_MULTICAST_TTL: {
1692		u_char ttl;
1693
1694		/*
1695		 * Set the IP time-to-live for outgoing multicast packets.
1696		 * The original multicast API required a char argument,
1697		 * which is inconsistent with the rest of the socket API.
1698		 * We allow either a char or an int.
1699		 */
1700		if (sopt->sopt_valsize == sizeof(u_char)) {
1701			error = sooptcopyin(sopt, &ttl, sizeof(u_char),
1702			    sizeof(u_char));
1703			if (error)
1704				break;
1705		} else {
1706			u_int ittl;
1707
1708			error = sooptcopyin(sopt, &ittl, sizeof(u_int),
1709			    sizeof(u_int));
1710			if (error)
1711				break;
1712			if (ittl > 255) {
1713				error = EINVAL;
1714				break;
1715			}
1716			ttl = (u_char)ittl;
1717		}
1718		imo = inp_findmoptions(inp);
1719		imo->imo_multicast_ttl = ttl;
1720		INP_UNLOCK(inp);
1721		break;
1722	}
1723
1724	case IP_MULTICAST_LOOP: {
1725		u_char loop;
1726
1727		/*
1728		 * Set the loopback flag for outgoing multicast packets.
1729		 * Must be zero or one.  The original multicast API required a
1730		 * char argument, which is inconsistent with the rest
1731		 * of the socket API.  We allow either a char or an int.
1732		 */
1733		if (sopt->sopt_valsize == sizeof(u_char)) {
1734			error = sooptcopyin(sopt, &loop, sizeof(u_char),
1735			    sizeof(u_char));
1736			if (error)
1737				break;
1738		} else {
1739			u_int iloop;
1740
1741			error = sooptcopyin(sopt, &iloop, sizeof(u_int),
1742					    sizeof(u_int));
1743			if (error)
1744				break;
1745			loop = (u_char)iloop;
1746		}
1747		imo = inp_findmoptions(inp);
1748		imo->imo_multicast_loop = !!loop;
1749		INP_UNLOCK(inp);
1750		break;
1751	}
1752
1753	case IP_ADD_MEMBERSHIP:
1754	case IP_ADD_SOURCE_MEMBERSHIP:
1755	case MCAST_JOIN_GROUP:
1756	case MCAST_JOIN_SOURCE_GROUP:
1757		error = inp_join_group(inp, sopt);
1758		break;
1759
1760	case IP_DROP_MEMBERSHIP:
1761	case IP_DROP_SOURCE_MEMBERSHIP:
1762	case MCAST_LEAVE_GROUP:
1763	case MCAST_LEAVE_SOURCE_GROUP:
1764		error = inp_leave_group(inp, sopt);
1765		break;
1766
1767	case IP_BLOCK_SOURCE:
1768	case IP_UNBLOCK_SOURCE:
1769	case MCAST_BLOCK_SOURCE:
1770	case MCAST_UNBLOCK_SOURCE:
1771		error = inp_change_source_filter(inp, sopt);
1772		break;
1773
1774	case IP_MSFILTER:
1775		error = inp_set_source_filters(inp, sopt);
1776		break;
1777
1778	default:
1779		error = EOPNOTSUPP;
1780		break;
1781	}
1782
1783	INP_UNLOCK_ASSERT(inp);
1784
1785	return (error);
1786}
1787