* Look up a source filter entry for a multicast group. * * inm is the group descriptor to work with. * addr is the IPv6 address to look up. * noalloc may be non-zero to suppress allocation of sources. * *pims will be set to the address of the retrieved or allocated source. * * SMPng: NOTE: may be called with locks held. * Return 0 if successful, otherwise return a non-zero error code. */
| 918 | * Return 0 if successful, otherwise return a non-zero error code. |
| 919 | */ |
| 920 | static int |
| 921 | in6m_get_source(struct in6_multi *inm, const struct in6_addr *addr, |
| 922 | const int noalloc, struct ip6_msource **pims) |
| 923 | { |
| 924 | struct ip6_msource find; |
| 925 | struct ip6_msource *ims, *nims; |
| 926 | #ifdef KTR |
| 927 | char ip6tbuf[INET6_ADDRSTRLEN]; |
| 928 | #endif |
| 929 | |
| 930 | find.im6s_addr = *addr; |
| 931 | ims = RB_FIND(ip6_msource_tree, &inm->in6m_srcs, &find); |
| 932 | if (ims == NULL && !noalloc) { |
| 933 | if (inm->in6m_nsrc == in6_mcast_maxgrpsrc) |
| 934 | return (ENOSPC); |
| 935 | nims = malloc(sizeof(struct ip6_msource), M_IP6MSOURCE, |
| 936 | M_NOWAIT | M_ZERO); |
| 937 | if (nims == NULL) |
| 938 | return (ENOMEM); |
| 939 | nims->im6s_addr = *addr; |
| 940 | RB_INSERT(ip6_msource_tree, &inm->in6m_srcs, nims); |
| 941 | ++inm->in6m_nsrc; |
| 942 | ims = nims; |
| 943 | CTR3(KTR_MLD, "%s: allocated %s as %p", __func__, |
| 944 | ip6_sprintf(ip6tbuf, addr), ims); |
| 945 | } |
| 946 | |
| 947 | *pims = ims; |
| 948 | return (0); |
| 949 | } |
| 950 | |
| 951 | /* |
| 952 | * Merge socket-layer source into MLD-layer source. |
no test coverage detected