]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/netinet/in_mcast.c
This commit was generated by cvs2svn to compensate for changes in r171537,
[FreeBSD/FreeBSD.git] / sys / netinet / in_mcast.c
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$");
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
63 union 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 };
72 typedef union sockunion sockunion_t;
73 #define __SOCKUNION_DECLARED
74 #endif /* __SOCKUNION_DECLARED */
75
76 static MALLOC_DEFINE(M_IPMADDR, "in_multi", "IPv4 multicast group");
77 static MALLOC_DEFINE(M_IPMOPTS, "ip_moptions", "IPv4 multicast options");
78 static 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  */
87 struct in_multihead in_multihead;       /* XXX BSS initialization */
88 struct mtx in_multi_mtx;
89 MTX_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  */
104 static int      imo_grow(struct ip_moptions *);
105 static int      imo_join_source(struct ip_moptions *, size_t, sockunion_t *);
106 static int      imo_leave_source(struct ip_moptions *, size_t, sockunion_t *);
107 static int      inp_change_source_filter(struct inpcb *, struct sockopt *);
108 static struct ip_moptions *
109                 inp_findmoptions(struct inpcb *);
110 static int      inp_get_source_filters(struct inpcb *, struct sockopt *);
111 static int      inp_join_group(struct inpcb *, struct sockopt *);
112 static int      inp_leave_group(struct inpcb *, struct sockopt *);
113 static int      inp_set_multicast_if(struct inpcb *, struct sockopt *);
114 static 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  */
120 static int
121 imo_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  */
171 static int
172 imo_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
202 static int
203 imo_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  */
232 size_t
233 imo_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  */
273 struct in_msource *
274 imo_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  */
309 struct in_multi *
310 in_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  */
398 void
399 in_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  */
431 void
432 in_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  */
461 static int
462 inp_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
652 out_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  */
661 static struct ip_moptions *
662 inp_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  */
714 void
715 inp_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  */
750 static int
751 inp_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  */
847 int
848 inp_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  */
943 static int
944 inp_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 in the unicast FIB for
1000                  * the given multicast destination; usually, this is the
1001                  * default route.
1002                  * If this lookup fails, attempt to use the first non-loopback
1003                  * interface with multicast capability in the system as a
1004                  * last resort. The legacy IPv4 ASM API requires that we do
1005                  * this in order to allow groups to be joined when the routing
1006                  * table has not yet been populated during boot.
1007                  * If all of these conditions fail, return EADDRNOTAVAIL, and
1008                  * reject the IPv4 multicast join.
1009                  */
1010                 if (mreqs.imr_interface.s_addr != INADDR_ANY) {
1011                         INADDR_TO_IFP(mreqs.imr_interface, ifp);
1012                 } else {
1013                         struct route ro;
1014
1015                         ro.ro_rt = NULL;
1016                         *(struct sockaddr_in *)&ro.ro_dst = gsa->sin;
1017                         rtalloc_ign(&ro, RTF_CLONING);
1018                         if (ro.ro_rt != NULL) {
1019                                 ifp = ro.ro_rt->rt_ifp;
1020                                 KASSERT(ifp != NULL, ("%s: null ifp",
1021                                     __func__));
1022                                 RTFREE(ro.ro_rt);
1023                         } else {
1024                                 struct in_ifaddr *ia;
1025                                 struct ifnet *mfp = NULL;
1026                                 TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) {
1027                                         mfp = ia->ia_ifp;
1028                                         if (!(mfp->if_flags & IFF_LOOPBACK) &&
1029                                              (mfp->if_flags & IFF_MULTICAST)) {
1030                                                 ifp = mfp;
1031                                                 break;
1032                                         }
1033                                 }
1034                         }
1035                 }
1036 #ifdef DIAGNOSTIC
1037                 if (bootverbose) {
1038                         printf("%s: imr_interface = %s, ifp = %p\n",
1039                             __func__, inet_ntoa(mreqs.imr_interface), ifp);
1040                 }
1041 #endif
1042                 break;
1043         }
1044
1045         case MCAST_JOIN_GROUP:
1046         case MCAST_JOIN_SOURCE_GROUP:
1047                 if (sopt->sopt_name == MCAST_JOIN_GROUP) {
1048                         error = sooptcopyin(sopt, &gsr,
1049                             sizeof(struct group_req),
1050                             sizeof(struct group_req));
1051                 } else if (sopt->sopt_name == MCAST_JOIN_SOURCE_GROUP) {
1052                         error = sooptcopyin(sopt, &gsr,
1053                             sizeof(struct group_source_req),
1054                             sizeof(struct group_source_req));
1055                 }
1056                 if (error)
1057                         return (error);
1058
1059                 if (gsa->sin.sin_family != AF_INET ||
1060                     gsa->sin.sin_len != sizeof(struct sockaddr_in))
1061                         return (EINVAL);
1062
1063                 /*
1064                  * Overwrite the port field if present, as the sockaddr
1065                  * being copied in may be matched with a binary comparison.
1066                  * XXX INET6
1067                  */
1068                 gsa->sin.sin_port = 0;
1069                 if (sopt->sopt_name == MCAST_JOIN_SOURCE_GROUP) {
1070                         if (ssa->sin.sin_family != AF_INET ||
1071                             ssa->sin.sin_len != sizeof(struct sockaddr_in))
1072                                 return (EINVAL);
1073                         ssa->sin.sin_port = 0;
1074                 }
1075
1076                 /*
1077                  * Obtain the ifp.
1078                  */
1079                 if (gsr.gsr_interface == 0 || if_index < gsr.gsr_interface)
1080                         return (EADDRNOTAVAIL);
1081                 ifp = ifnet_byindex(gsr.gsr_interface);
1082
1083                 break;
1084
1085         default:
1086 #ifdef DIAGNOSTIC
1087                 if (bootverbose) {
1088                         printf("%s: unknown sopt_name %d\n", __func__,
1089                             sopt->sopt_name);
1090                 }
1091 #endif
1092                 return (EOPNOTSUPP);
1093                 break;
1094         }
1095
1096         if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr)))
1097                 return (EINVAL);
1098
1099         if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0)
1100                 return (EADDRNOTAVAIL);
1101
1102         /*
1103          * Check if we already hold membership of this group for this inpcb.
1104          * If so, we do not need to perform the initial join.
1105          */
1106         imo = inp_findmoptions(inp);
1107         idx = imo_match_group(imo, ifp, &gsa->sa);
1108         if (idx != -1) {
1109                 if (ssa->ss.ss_family != AF_UNSPEC) {
1110                         /*
1111                          * Attempting to join an ASM group (when already
1112                          * an ASM or SSM member) is an error.
1113                          */
1114                         error = EADDRNOTAVAIL;
1115                 } else {
1116                         imf = &imo->imo_mfilters[idx];
1117                         if (imf->imf_nsources == 0) {
1118                                 /*
1119                                  * Attempting to join an SSM group (when
1120                                  * already an ASM member) is an error.
1121                                  */
1122                                 error = EINVAL;
1123                         } else {
1124                                 /*
1125                                  * Attempting to join an SSM group (when
1126                                  * already an SSM member) means "add this
1127                                  * source to the inclusive filter list".
1128                                  */
1129                                 error = imo_join_source(imo, idx, ssa);
1130                         }
1131                 }
1132                 goto out_locked;
1133         }
1134
1135         /*
1136          * Call imo_grow() to reallocate the membership and source filter
1137          * vectors if they are full. If the size would exceed the hard limit,
1138          * then we know we've really run out of entries. We keep the INP
1139          * lock held to avoid introducing a race condition.
1140          */
1141         if (imo->imo_num_memberships == imo->imo_max_memberships) {
1142                 error = imo_grow(imo);
1143                 if (error)
1144                         goto out_locked;
1145         }
1146
1147         /*
1148          * So far, so good: perform the layer 3 join, layer 2 join,
1149          * and make an IGMP announcement if needed.
1150          */
1151         inm = in_addmulti(&gsa->sin.sin_addr, ifp);
1152         if (inm == NULL) {
1153                 error = ENOBUFS;
1154                 goto out_locked;
1155         }
1156         idx = imo->imo_num_memberships;
1157         imo->imo_membership[idx] = inm;
1158         imo->imo_num_memberships++;
1159
1160         KASSERT(imo->imo_mfilters != NULL,
1161             ("%s: imf_mfilters vector was not allocated", __func__));
1162         imf = &imo->imo_mfilters[idx];
1163         KASSERT(TAILQ_EMPTY(&imf->imf_sources),
1164             ("%s: imf_sources not empty", __func__));
1165
1166         /*
1167          * If this is a new SSM group join (i.e. a source was specified
1168          * with this group), add this source to the filter list.
1169          */
1170         if (ssa->ss.ss_family != AF_UNSPEC) {
1171                 /*
1172                  * An initial SSM join implies that this socket's membership
1173                  * of the multicast group is now in inclusive mode.
1174                  */
1175                 imf->imf_fmode = MCAST_INCLUDE;
1176
1177                 error = imo_join_source(imo, idx, ssa);
1178                 if (error) {
1179                         /*
1180                          * Drop inp lock before calling in_delmulti(),
1181                          * to prevent a lock order reversal.
1182                          */
1183                         --imo->imo_num_memberships;
1184                         INP_UNLOCK(inp);
1185                         in_delmulti(inm);
1186                         return (error);
1187                 }
1188         }
1189
1190 out_locked:
1191         INP_UNLOCK(inp);
1192         return (error);
1193 }
1194
1195 /*
1196  * Leave an IPv4 multicast group on an inpcb, possibly with a source.
1197  */
1198 static int
1199 inp_leave_group(struct inpcb *inp, struct sockopt *sopt)
1200 {
1201         struct group_source_req          gsr;
1202         struct ip_mreq_source            mreqs;
1203         sockunion_t                     *gsa, *ssa;
1204         struct ifnet                    *ifp;
1205         struct in_mfilter               *imf;
1206         struct ip_moptions              *imo;
1207         struct in_msource               *ims, *tims;
1208         struct in_multi                 *inm;
1209         size_t                           idx;
1210         int                              error;
1211
1212         ifp = NULL;
1213         error = 0;
1214
1215         memset(&gsr, 0, sizeof(struct group_source_req));
1216         gsa = (sockunion_t *)&gsr.gsr_group;
1217         gsa->ss.ss_family = AF_UNSPEC;
1218         ssa = (sockunion_t *)&gsr.gsr_source;
1219         ssa->ss.ss_family = AF_UNSPEC;
1220
1221         switch (sopt->sopt_name) {
1222         case IP_DROP_MEMBERSHIP:
1223         case IP_DROP_SOURCE_MEMBERSHIP:
1224                 if (sopt->sopt_name == IP_DROP_MEMBERSHIP) {
1225                         error = sooptcopyin(sopt, &mreqs,
1226                             sizeof(struct ip_mreq),
1227                             sizeof(struct ip_mreq));
1228                         /*
1229                          * Swap interface and sourceaddr arguments,
1230                          * as ip_mreq and ip_mreq_source are laid
1231                          * out differently.
1232                          */
1233                         mreqs.imr_interface = mreqs.imr_sourceaddr;
1234                         mreqs.imr_sourceaddr.s_addr = INADDR_ANY;
1235                 } else if (sopt->sopt_name == IP_DROP_SOURCE_MEMBERSHIP) {
1236                         error = sooptcopyin(sopt, &mreqs,
1237                             sizeof(struct ip_mreq_source),
1238                             sizeof(struct ip_mreq_source));
1239                 }
1240                 if (error)
1241                         return (error);
1242
1243                 gsa->sin.sin_family = AF_INET;
1244                 gsa->sin.sin_len = sizeof(struct sockaddr_in);
1245                 gsa->sin.sin_addr = mreqs.imr_multiaddr;
1246
1247                 if (sopt->sopt_name == IP_DROP_SOURCE_MEMBERSHIP) {
1248                         ssa->sin.sin_family = AF_INET;
1249                         ssa->sin.sin_len = sizeof(struct sockaddr_in);
1250                         ssa->sin.sin_addr = mreqs.imr_sourceaddr;
1251                 }
1252
1253                 if (gsa->sin.sin_addr.s_addr != INADDR_ANY)
1254                         INADDR_TO_IFP(mreqs.imr_interface, ifp);
1255
1256 #ifdef DIAGNOSTIC
1257                 if (bootverbose) {
1258                         printf("%s: imr_interface = %s, ifp = %p\n",
1259                             __func__, inet_ntoa(mreqs.imr_interface), ifp);
1260                 }
1261 #endif
1262                 break;
1263
1264         case MCAST_LEAVE_GROUP:
1265         case MCAST_LEAVE_SOURCE_GROUP:
1266                 if (sopt->sopt_name == MCAST_LEAVE_GROUP) {
1267                         error = sooptcopyin(sopt, &gsr,
1268                             sizeof(struct group_req),
1269                             sizeof(struct group_req));
1270                 } else if (sopt->sopt_name == MCAST_LEAVE_SOURCE_GROUP) {
1271                         error = sooptcopyin(sopt, &gsr,
1272                             sizeof(struct group_source_req),
1273                             sizeof(struct group_source_req));
1274                 }
1275                 if (error)
1276                         return (error);
1277
1278                 if (gsa->sin.sin_family != AF_INET ||
1279                     gsa->sin.sin_len != sizeof(struct sockaddr_in))
1280                         return (EINVAL);
1281
1282                 if (sopt->sopt_name == MCAST_LEAVE_SOURCE_GROUP) {
1283                         if (ssa->sin.sin_family != AF_INET ||
1284                             ssa->sin.sin_len != sizeof(struct sockaddr_in))
1285                                 return (EINVAL);
1286                 }
1287
1288                 if (gsr.gsr_interface == 0 || if_index < gsr.gsr_interface)
1289                         return (EADDRNOTAVAIL);
1290
1291                 ifp = ifnet_byindex(gsr.gsr_interface);
1292                 break;
1293
1294         default:
1295 #ifdef DIAGNOSTIC
1296                 if (bootverbose) {
1297                         printf("%s: unknown sopt_name %d\n", __func__,
1298                             sopt->sopt_name);
1299                 }
1300 #endif
1301                 return (EOPNOTSUPP);
1302                 break;
1303         }
1304
1305         if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr)))
1306                 return (EINVAL);
1307
1308         /*
1309          * Find the membership in the membership array.
1310          */
1311         imo = inp_findmoptions(inp);
1312         idx = imo_match_group(imo, ifp, &gsa->sa);
1313         if (idx == -1) {
1314                 error = EADDRNOTAVAIL;
1315                 goto out_locked;
1316         }
1317         imf = &imo->imo_mfilters[idx];
1318
1319         /*
1320          * If we were instructed only to leave a given source, do so.
1321          */
1322         if (ssa->ss.ss_family != AF_UNSPEC) {
1323                 if (imf->imf_nsources == 0 ||
1324                     imf->imf_fmode == MCAST_EXCLUDE) {
1325                         /*
1326                          * Attempting to SSM leave an ASM group
1327                          * is an error; should use *_BLOCK_SOURCE instead.
1328                          * Attempting to SSM leave a source in a group when
1329                          * the socket is in 'exclude mode' is also an error.
1330                          */
1331                         error = EINVAL;
1332                 } else {
1333                         error = imo_leave_source(imo, idx, ssa);
1334                 }
1335                 /*
1336                  * If an error occurred, or this source is not the last
1337                  * source in the group, do not leave the whole group.
1338                  */
1339                 if (error || imf->imf_nsources > 0)
1340                         goto out_locked;
1341         }
1342
1343         /*
1344          * Give up the multicast address record to which the membership points.
1345          */
1346         inm = imo->imo_membership[idx];
1347         in_delmulti(inm);
1348
1349         /*
1350          * Free any source filters for this group if they exist.
1351          * Revert inpcb to the default MCAST_EXCLUDE state.
1352          */
1353         if (imo->imo_mfilters != NULL) {
1354                 TAILQ_FOREACH_SAFE(ims, &imf->imf_sources, ims_next, tims) {
1355                         TAILQ_REMOVE(&imf->imf_sources, ims, ims_next);
1356                         FREE(ims, M_IPMSOURCE);
1357                         imf->imf_nsources--;
1358                 }
1359                 KASSERT(imf->imf_nsources == 0,
1360                     ("%s: imf_nsources not 0", __func__));
1361                 KASSERT(TAILQ_EMPTY(&imf->imf_sources),
1362                     ("%s: imf_sources not empty", __func__));
1363                 imf->imf_fmode = MCAST_EXCLUDE;
1364         }
1365
1366         /*
1367          * Remove the gap in the membership array.
1368          */
1369         for (++idx; idx < imo->imo_num_memberships; ++idx)
1370                 imo->imo_membership[idx-1] = imo->imo_membership[idx];
1371         imo->imo_num_memberships--;
1372
1373 out_locked:
1374         INP_UNLOCK(inp);
1375         return (error);
1376 }
1377
1378 /*
1379  * Select the interface for transmitting IPv4 multicast datagrams.
1380  *
1381  * Either an instance of struct in_addr or an instance of struct ip_mreqn
1382  * may be passed to this socket option. An address of INADDR_ANY or an
1383  * interface index of 0 is used to remove a previous selection.
1384  * When no interface is selected, one is chosen for every send.
1385  */
1386 static int
1387 inp_set_multicast_if(struct inpcb *inp, struct sockopt *sopt)
1388 {
1389         struct in_addr           addr;
1390         struct ip_mreqn          mreqn;
1391         struct ifnet            *ifp;
1392         struct ip_moptions      *imo;
1393         int                      error;
1394
1395         if (sopt->sopt_valsize == sizeof(struct ip_mreqn)) {
1396                 /*
1397                  * An interface index was specified using the
1398                  * Linux-derived ip_mreqn structure.
1399                  */
1400                 error = sooptcopyin(sopt, &mreqn, sizeof(struct ip_mreqn),
1401                     sizeof(struct ip_mreqn));
1402                 if (error)
1403                         return (error);
1404
1405                 if (mreqn.imr_ifindex < 0 || if_index < mreqn.imr_ifindex)
1406                         return (EINVAL);
1407
1408                 if (mreqn.imr_ifindex == 0) {
1409                         ifp = NULL;
1410                 } else {
1411                         ifp = ifnet_byindex(mreqn.imr_ifindex);
1412                         if (ifp == NULL)
1413                                 return (EADDRNOTAVAIL);
1414                 }
1415         } else {
1416                 /*
1417                  * An interface was specified by IPv4 address.
1418                  * This is the traditional BSD usage.
1419                  */
1420                 error = sooptcopyin(sopt, &addr, sizeof(struct in_addr),
1421                     sizeof(struct in_addr));
1422                 if (error)
1423                         return (error);
1424                 if (addr.s_addr == INADDR_ANY) {
1425                         ifp = NULL;
1426                 } else {
1427                         INADDR_TO_IFP(addr, ifp);
1428                         if (ifp == NULL)
1429                                 return (EADDRNOTAVAIL);
1430                 }
1431 #ifdef DIAGNOSTIC
1432                 if (bootverbose) {
1433                         printf("%s: ifp = %p, addr = %s\n",
1434                             __func__, ifp, inet_ntoa(addr)); /* XXX INET6 */
1435                 }
1436 #endif
1437         }
1438
1439         /* Reject interfaces which do not support multicast. */
1440         if (ifp != NULL && (ifp->if_flags & IFF_MULTICAST) == 0)
1441                 return (EOPNOTSUPP);
1442
1443         imo = inp_findmoptions(inp);
1444         imo->imo_multicast_ifp = ifp;
1445         imo->imo_multicast_addr.s_addr = INADDR_ANY;
1446         INP_UNLOCK(inp);
1447
1448         return (0);
1449 }
1450
1451 /*
1452  * Atomically set source filters on a socket for an IPv4 multicast group.
1453  */
1454 static int
1455 inp_set_source_filters(struct inpcb *inp, struct sockopt *sopt)
1456 {
1457         struct __msfilterreq     msfr;
1458         sockunion_t             *gsa;
1459         struct ifnet            *ifp;
1460         struct in_mfilter       *imf;
1461         struct ip_moptions      *imo;
1462         struct in_msource       *ims, *tims;
1463         size_t                   idx;
1464         int                      error;
1465
1466         error = sooptcopyin(sopt, &msfr, sizeof(struct __msfilterreq),
1467             sizeof(struct __msfilterreq));
1468         if (error)
1469                 return (error);
1470
1471         if (msfr.msfr_nsrcs > IP_MAX_SOURCE_FILTER ||
1472             (msfr.msfr_fmode != MCAST_EXCLUDE &&
1473              msfr.msfr_fmode != MCAST_INCLUDE))
1474                 return (EINVAL);
1475
1476         if (msfr.msfr_group.ss_family != AF_INET ||
1477             msfr.msfr_group.ss_len != sizeof(struct sockaddr_in))
1478                 return (EINVAL);
1479
1480         gsa = (sockunion_t *)&msfr.msfr_group;
1481         if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr)))
1482                 return (EINVAL);
1483
1484         gsa->sin.sin_port = 0;  /* ignore port */
1485
1486         if (msfr.msfr_ifindex == 0 || if_index < msfr.msfr_ifindex)
1487                 return (EADDRNOTAVAIL);
1488
1489         ifp = ifnet_byindex(msfr.msfr_ifindex);
1490         if (ifp == NULL)
1491                 return (EADDRNOTAVAIL);
1492
1493         /*
1494          * Take the INP lock.
1495          * Check if this socket is a member of this group.
1496          */
1497         imo = inp_findmoptions(inp);
1498         idx = imo_match_group(imo, ifp, &gsa->sa);
1499         if (idx == -1 || imo->imo_mfilters == NULL) {
1500                 error = EADDRNOTAVAIL;
1501                 goto out_locked;
1502         }
1503         imf = &imo->imo_mfilters[idx];
1504
1505 #ifdef DIAGNOSTIC
1506         if (bootverbose)
1507                 printf("%s: clearing source list\n", __func__);
1508 #endif
1509
1510         /*
1511          * Remove any existing source filters.
1512          */
1513         TAILQ_FOREACH_SAFE(ims, &imf->imf_sources, ims_next, tims) {
1514                 TAILQ_REMOVE(&imf->imf_sources, ims, ims_next);
1515                 FREE(ims, M_IPMSOURCE);
1516                 imf->imf_nsources--;
1517         }
1518         KASSERT(imf->imf_nsources == 0,
1519             ("%s: source list not cleared", __func__));
1520
1521         /*
1522          * Apply any new source filters, if present.
1523          */
1524         if (msfr.msfr_nsrcs > 0) {
1525                 struct in_msource       **pnims;
1526                 struct in_msource       *nims;
1527                 struct sockaddr_storage *kss;
1528                 struct sockaddr_storage *pkss;
1529                 sockunion_t             *psu;
1530                 int                      i, j;
1531
1532                 /*
1533                  * Drop the inp lock so we may sleep if we need to
1534                  * in order to satisfy a malloc request.
1535                  * We will re-take it before changing socket state.
1536                  */
1537                 INP_UNLOCK(inp);
1538 #ifdef DIAGNOSTIC
1539                 if (bootverbose) {
1540                         printf("%s: loading %lu source list entries\n",
1541                             __func__, (unsigned long)msfr.msfr_nsrcs);
1542                 }
1543 #endif
1544                 /*
1545                  * Make a copy of the user-space source vector so
1546                  * that we may copy them with a single copyin. This
1547                  * allows us to deal with page faults up-front.
1548                  */
1549                 MALLOC(kss, struct sockaddr_storage *,
1550                     sizeof(struct sockaddr_storage) * msfr.msfr_nsrcs,
1551                     M_TEMP, M_WAITOK);
1552                 error = copyin(msfr.msfr_srcs, kss,
1553                     sizeof(struct sockaddr_storage) * msfr.msfr_nsrcs);
1554                 if (error) {
1555                         FREE(kss, M_TEMP);
1556                         return (error);
1557                 }
1558
1559                 /*
1560                  * Perform argument checking on every sockaddr_storage
1561                  * structure in the vector provided to us. Overwrite
1562                  * fields which should not apply to source entries.
1563                  * TODO: Check for duplicate sources on this pass.
1564                  */
1565                 psu = (sockunion_t *)kss;
1566                 for (i = 0; i < msfr.msfr_nsrcs; i++, psu++) {
1567                         switch (psu->ss.ss_family) {
1568                         case AF_INET:
1569                                 if (psu->sin.sin_len !=
1570                                     sizeof(struct sockaddr_in)) {
1571                                         error = EINVAL;
1572                                 } else {
1573                                         psu->sin.sin_port = 0;
1574                                 }
1575                                 break;
1576 #ifdef notyet
1577                         case AF_INET6;
1578                                 if (psu->sin6.sin6_len !=
1579                                     sizeof(struct sockaddr_in6)) {
1580                                         error = EINVAL;
1581                                 } else {
1582                                         psu->sin6.sin6_port = 0;
1583                                         psu->sin6.sin6_flowinfo = 0;
1584                                 }
1585                                 break;
1586 #endif
1587                         default:
1588                                 error = EAFNOSUPPORT;
1589                                 break;
1590                         }
1591                         if (error)
1592                                 break;
1593                 }
1594                 if (error) {
1595                         FREE(kss, M_TEMP);
1596                         return (error);
1597                 }
1598
1599                 /*
1600                  * Allocate a block to track all the in_msource
1601                  * entries we are about to allocate, in case we
1602                  * abruptly need to free them.
1603                  */
1604                 MALLOC(pnims, struct in_msource **,
1605                     sizeof(struct in_msource *) * msfr.msfr_nsrcs,
1606                     M_TEMP, M_WAITOK | M_ZERO);
1607
1608                 /*
1609                  * Allocate up to nsrcs individual chunks.
1610                  * If we encounter an error, backtrack out of
1611                  * all allocations cleanly; updates must be atomic.
1612                  */
1613                 pkss = kss;
1614                 nims = NULL;
1615                 for (i = 0; i < msfr.msfr_nsrcs; i++, pkss++) {
1616                         MALLOC(nims, struct in_msource *,
1617                             sizeof(struct in_msource) * msfr.msfr_nsrcs,
1618                             M_IPMSOURCE, M_WAITOK | M_ZERO);
1619                         pnims[i] = nims;
1620                 }
1621                 if (i < msfr.msfr_nsrcs) {
1622                         for (j = 0; j < i; j++) {
1623                                 if (pnims[j] != NULL)
1624                                         FREE(pnims[j], M_IPMSOURCE);
1625                         }
1626                         FREE(pnims, M_TEMP);
1627                         FREE(kss, M_TEMP);
1628                         return (ENOBUFS);
1629                 }
1630
1631                 INP_UNLOCK_ASSERT(inp);
1632
1633                 /*
1634                  * Finally, apply the filters to the socket.
1635                  * Re-take the inp lock; we are changing socket state.
1636                  */
1637                 pkss = kss;
1638                 INP_LOCK(inp);
1639                 for (i = 0; i < msfr.msfr_nsrcs; i++, pkss++) {
1640                         memcpy(&(pnims[i]->ims_addr), pkss,
1641                             sizeof(struct sockaddr_storage));
1642                         TAILQ_INSERT_TAIL(&imf->imf_sources, pnims[i],
1643                             ims_next);
1644                         imf->imf_nsources++;
1645                 }
1646                 FREE(pnims, M_TEMP);
1647                 FREE(kss, M_TEMP);
1648         }
1649
1650         /*
1651          * Update the filter mode on the socket before releasing the inpcb.
1652          */
1653         INP_LOCK_ASSERT(inp);
1654         imf->imf_fmode = msfr.msfr_fmode;
1655
1656 out_locked:
1657         INP_UNLOCK(inp);
1658         return (error);
1659 }
1660
1661 /*
1662  * Set the IP multicast options in response to user setsockopt().
1663  *
1664  * Many of the socket options handled in this function duplicate the
1665  * functionality of socket options in the regular unicast API. However,
1666  * it is not possible to merge the duplicate code, because the idempotence
1667  * of the IPv4 multicast part of the BSD Sockets API must be preserved;
1668  * the effects of these options must be treated as separate and distinct.
1669  */
1670 int
1671 inp_setmoptions(struct inpcb *inp, struct sockopt *sopt)
1672 {
1673         struct ip_moptions      *imo;
1674         int                      error;
1675
1676         error = 0;
1677
1678         switch (sopt->sopt_name) {
1679         case IP_MULTICAST_VIF: {
1680                 int vifi;
1681                 /*
1682                  * Select a multicast VIF for transmission.
1683                  * Only useful if multicast forwarding is active.
1684                  */
1685                 if (legal_vif_num == NULL) {
1686                         error = EOPNOTSUPP;
1687                         break;
1688                 }
1689                 error = sooptcopyin(sopt, &vifi, sizeof(int), sizeof(int));
1690                 if (error)
1691                         break;
1692                 if (!legal_vif_num(vifi) && (vifi != -1)) {
1693                         error = EINVAL;
1694                         break;
1695                 }
1696                 imo = inp_findmoptions(inp);
1697                 imo->imo_multicast_vif = vifi;
1698                 INP_UNLOCK(inp);
1699                 break;
1700         }
1701
1702         case IP_MULTICAST_IF:
1703                 error = inp_set_multicast_if(inp, sopt);
1704                 break;
1705
1706         case IP_MULTICAST_TTL: {
1707                 u_char ttl;
1708
1709                 /*
1710                  * Set the IP time-to-live for outgoing multicast packets.
1711                  * The original multicast API required a char argument,
1712                  * which is inconsistent with the rest of the socket API.
1713                  * We allow either a char or an int.
1714                  */
1715                 if (sopt->sopt_valsize == sizeof(u_char)) {
1716                         error = sooptcopyin(sopt, &ttl, sizeof(u_char),
1717                             sizeof(u_char));
1718                         if (error)
1719                                 break;
1720                 } else {
1721                         u_int ittl;
1722
1723                         error = sooptcopyin(sopt, &ittl, sizeof(u_int),
1724                             sizeof(u_int));
1725                         if (error)
1726                                 break;
1727                         if (ittl > 255) {
1728                                 error = EINVAL;
1729                                 break;
1730                         }
1731                         ttl = (u_char)ittl;
1732                 }
1733                 imo = inp_findmoptions(inp);
1734                 imo->imo_multicast_ttl = ttl;
1735                 INP_UNLOCK(inp);
1736                 break;
1737         }
1738
1739         case IP_MULTICAST_LOOP: {
1740                 u_char loop;
1741
1742                 /*
1743                  * Set the loopback flag for outgoing multicast packets.
1744                  * Must be zero or one.  The original multicast API required a
1745                  * char argument, which is inconsistent with the rest
1746                  * of the socket API.  We allow either a char or an int.
1747                  */
1748                 if (sopt->sopt_valsize == sizeof(u_char)) {
1749                         error = sooptcopyin(sopt, &loop, sizeof(u_char),
1750                             sizeof(u_char));
1751                         if (error)
1752                                 break;
1753                 } else {
1754                         u_int iloop;
1755
1756                         error = sooptcopyin(sopt, &iloop, sizeof(u_int),
1757                                             sizeof(u_int));
1758                         if (error)
1759                                 break;
1760                         loop = (u_char)iloop;
1761                 }
1762                 imo = inp_findmoptions(inp);
1763                 imo->imo_multicast_loop = !!loop;
1764                 INP_UNLOCK(inp);
1765                 break;
1766         }
1767
1768         case IP_ADD_MEMBERSHIP:
1769         case IP_ADD_SOURCE_MEMBERSHIP:
1770         case MCAST_JOIN_GROUP:
1771         case MCAST_JOIN_SOURCE_GROUP:
1772                 error = inp_join_group(inp, sopt);
1773                 break;
1774
1775         case IP_DROP_MEMBERSHIP:
1776         case IP_DROP_SOURCE_MEMBERSHIP:
1777         case MCAST_LEAVE_GROUP:
1778         case MCAST_LEAVE_SOURCE_GROUP:
1779                 error = inp_leave_group(inp, sopt);
1780                 break;
1781
1782         case IP_BLOCK_SOURCE:
1783         case IP_UNBLOCK_SOURCE:
1784         case MCAST_BLOCK_SOURCE:
1785         case MCAST_UNBLOCK_SOURCE:
1786                 error = inp_change_source_filter(inp, sopt);
1787                 break;
1788
1789         case IP_MSFILTER:
1790                 error = inp_set_source_filters(inp, sopt);
1791                 break;
1792
1793         default:
1794                 error = EOPNOTSUPP;
1795                 break;
1796         }
1797
1798         INP_UNLOCK_ASSERT(inp);
1799
1800         return (error);
1801 }