1 /*
   2  * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include <string.h>
  27 
  28 #include "nio_multicast.h"
  29 
  30 #define COPY_INET6_ADDRESS(env, source, target) \
  31      (*env)->GetByteArrayRegion(env, source, 0, 16, target)
  32 
  33 /**
  34  * Initialize a group_req structure with the given interface index and IPv4
  35  * multicast group.
  36  */
  37 void initGroupReq4(JNIEnv* env, struct group_req *req, jint index, jint group)
  38 {
  39     struct sockaddr_in* sin;
  40 
  41 #ifdef WIN32
  42     req->gr_interface = (ULONG)index;
  43 #else
  44     req->gr_interface = (uint32_t)index;
  45 #endif
  46 
  47     sin = (struct sockaddr_in*)&(req->gr_group);
  48     memset(sin, 0, sizeof(struct sockaddr_in));
  49     sin->sin_family = AF_INET;
  50     sin->sin_addr.s_addr = htonl(group);
  51 }
  52 
  53 /**
  54  * Initialize a group_source_req structure with the given interface index, IPv4
  55  * multicast group, and IPv4 source address.
  56  */
  57 void initGroupSourceReq4(JNIEnv* env, struct group_source_req *req,
  58                          jint index, jint group, jint source)
  59 {
  60     struct sockaddr_in* sin;
  61 
  62 #ifdef WIN32
  63     req->gsr_interface = (ULONG)index;
  64 #else
  65     req->gsr_interface = (uint32_t)index;
  66 #endif
  67 
  68     sin = (struct sockaddr_in*)&(req->gsr_group);
  69     memset(sin, 0, sizeof(struct sockaddr_in));
  70     sin->sin_family = AF_INET;
  71     sin->sin_addr.s_addr = htonl(group);
  72 
  73     sin = (struct sockaddr_in*)&(req->gsr_source);
  74     memset(sin, 0, sizeof(struct sockaddr_in));
  75     sin->sin_family = AF_INET;
  76     sin->sin_addr.s_addr = htonl(source);
  77 }
  78 
  79 /**
  80  * Initialize a group_req structure with the given interface index and IPv6
  81  * multicast group.
  82  */
  83 void initGroupReq6(JNIEnv* env, struct group_req *req, jint index, jbyteArray group)
  84 {
  85     struct sockaddr_in6* sin6;
  86 
  87 #ifdef WIN32
  88     req->gr_interface = (ULONG)index;
  89 #else
  90     req->gr_interface = (uint32_t)index;
  91 #endif
  92 
  93     sin6 = (struct sockaddr_in6*)&(req->gr_group);
  94     memset(sin6, 0, sizeof(struct sockaddr_in6));
  95     sin6->sin6_family = AF_INET6;
  96     COPY_INET6_ADDRESS(env, group, (jbyte*)&(sin6->sin6_addr));
  97 }
  98 
  99 /**
 100  * Initialize a group_source req structure with the given interface index, IPv6
 101  * multicast group, and IPv6 source address.
 102  */
 103 void initGroupSourceReq6(JNIEnv* env, struct group_source_req *req,
 104                          int index, jbyteArray group, jbyteArray source)
 105 {
 106     struct sockaddr_in6* sin6;
 107 
 108 #ifdef WIN32
 109     req->gsr_interface = (ULONG)index;
 110 #else
 111     req->gsr_interface = (uint32_t)index;
 112 #endif
 113 
 114     sin6 = (struct sockaddr_in6*)&(req->gsr_group);
 115     memset(sin6, 0, sizeof(struct sockaddr_in6));
 116     sin6->sin6_family = AF_INET6;
 117     COPY_INET6_ADDRESS(env, group, (jbyte*)&(sin6->sin6_addr));
 118 
 119     sin6 = (struct sockaddr_in6*)&(req->gsr_source);
 120     memset(sin6, 0, sizeof(struct sockaddr_in6));
 121     sin6->sin6_family = AF_INET6;
 122     COPY_INET6_ADDRESS(env, source, (jbyte*)&(sin6->sin6_addr));
 123 }