OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [native/] [jni/] [java-net/] [gnu_java_net_VMPlainSocketImpl.c] - Blame information for rev 774

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 774 jeremybenn
/* VMPlainSocketImpl.c - Native methods for PlainSocketImpl class
2
   Copyright (C) 2005, 2006 Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
#ifdef HAVE_CONFIG_H
40
#include <config.h>
41
#endif /* HAVE_CONFIG_H */
42
 
43
#include <config-int.h>
44
 
45
#include <sys/ioctl.h>
46
#include <sys/types.h>
47
#include <sys/socket.h>
48
#include <sys/time.h>
49
#ifdef HAVE_IFADDRS_H
50
#include <ifaddrs.h>
51
#endif
52
#include <netinet/in.h>
53
#include <netinet/tcp.h>
54
#ifdef HAVE_NET_IF_H
55
#include <net/if.h>
56
#endif
57
#include <errno.h>
58
#include <stdlib.h>
59
#include <stdio.h>
60
#include <string.h>
61
#include <unistd.h>
62
 
63
#include <jni.h>
64
#include <jcl.h>
65
 
66
#include "cpnative.h"
67
#include "cpnet.h"
68
#include "cpio.h"
69
#include "javanet.h"
70
 
71
#include "gnu_java_net_VMPlainSocketImpl.h"
72
 
73
#define THROW_NO_NETWORK(env) JCL_ThrowException (env, "java/lang/InternalError", "this platform not configured for network support")
74
#define THROW_NO_IPV6(env)    JCL_ThrowException (env, "java/lang/InternalError", "IPv6 support not available")
75
 
76
/*
77
 * Class:     gnu_java_net_VMPlainSocketImpl
78
 * Method:    bind
79
 * Signature: (I[BI)V
80
 */
81
JNIEXPORT void JNICALL
82
Java_gnu_java_net_VMPlainSocketImpl_bind (JNIEnv *env,
83
                                          jclass clazz __attribute__((unused)),
84
                                          jint fd, jbyteArray addr, jint port)
85
{
86
  struct sockaddr_in sockaddr;
87
  jbyte *elems = NULL;
88
  int ret;
89
 
90
  if (addr != NULL)
91
    elems = (*env)->GetByteArrayElements (env, addr, NULL);
92
 
93
  memset(&sockaddr, 0, sizeof (struct sockaddr_in));
94
  sockaddr.sin_family = AF_INET;
95
  sockaddr.sin_port = htons (port);
96
  /* addr is already in network byte order. */
97
  if (elems != NULL)
98
    sockaddr.sin_addr.s_addr = *((uint32_t *) elems);
99
  else
100
    sockaddr.sin_addr.s_addr = INADDR_ANY;
101
 
102
  /* bind(2) from BSD says bind will never return EINTR */
103
  /* bind is not a blocking system call */
104
  ret = bind (fd, (struct sockaddr *) &sockaddr, sizeof (struct sockaddr_in));
105
 
106
  if (elems != NULL)
107
    (*env)->ReleaseByteArrayElements (env, addr, elems, JNI_ABORT);
108
 
109
  if (-1 == ret)
110
    JCL_ThrowException (env, BIND_EXCEPTION, strerror (errno));
111
 
112
  cpio_closeOnExec(ret);
113
}
114
 
115
 
116
/*
117
 * Class:     gnu_java_net_VMPlainSocketImpl
118
 * Method:    bind6
119
 * Signature: (I[BI)V
120
 */
121
JNIEXPORT void JNICALL
122
Java_gnu_java_net_VMPlainSocketImpl_bind6 (JNIEnv *env,
123
                                           jclass c __attribute__((unused)),
124
                                           jint fd, jbyteArray addr, jint port)
125
{
126
#ifdef HAVE_INET6
127
  struct sockaddr_in6 sockaddr;
128
  jbyte *elems;
129
  int ret;
130
 
131
  elems = (*env)->GetByteArrayElements (env, addr, NULL);
132
 
133
  memset (&sockaddr, 0, sizeof (struct sockaddr_in6));
134
  sockaddr.sin6_family = AF_INET6;
135
  sockaddr.sin6_port = htons (port);
136
  memcpy (&sockaddr.sin6_addr.s6_addr, elems, 16);
137
 
138
  /* bind(2) from BSD says bind will never return EINTR */
139
  /* bind is not a blocking system call */
140
  ret = bind (fd, (struct sockaddr *) &sockaddr,
141
              sizeof (struct sockaddr_in6));
142
 
143
  (*env)->ReleaseByteArrayElements (env, addr, elems, JNI_ABORT);
144
 
145
  if (-1 == ret)
146
    JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
147
#else
148
  THROW_NO_IPV6(env);
149
#endif
150
}
151
 
152
 
153
/*
154
 * Class:     gnu_java_net_VMPlainSocketImpl
155
 * Method:    listen
156
 * Signature: (II)V
157
 */
158
JNIEXPORT void JNICALL
159
Java_gnu_java_net_VMPlainSocketImpl_listen (JNIEnv *env,
160
                                            jclass c __attribute__((unused)),
161
                                            jint fd, jint backlog)
162
{
163
  int ret;
164
 
165
  /* listen(2) says that this call will never return EINTR */
166
  /* listen is not a blocking system call */
167
  if ((ret = listen (fd, backlog)) == -1)
168
    JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
169
}
170
 
171
 
172
/* These constants are also defined in java/net/SocketOptions.java.
173
 * Except for CPNET_IP_TTL which is defined in
174
 * vm/reference/gnu/java/net/VMPlainSocketImpl.java .
175
 */
176
enum java_sockopt {
177
  CPNET_SO_KEEPALIVE = 0x8,
178
  CPNET_SO_LINGER = 0x80,
179
  CPNET_SO_TIMEOUT = 0x1006,
180
  CPNET_SO_BINDADDR = 0x0F,
181
  CPNET_SO_SNDBUF = 0x1001,
182
  CPNET_SO_RCVBUF = 0x1002,
183
  CPNET_SO_REUSEADDR = 0x04,
184
  CPNET_SO_BROADCAST = 0x20,
185
  CPNET_SO_OOBINLINE = 0x1003,
186
  CPNET_TCP_NODELAY = 0x01,
187
  CPNET_IP_MULTICAST_IF = 0x10,
188
  CPNET_IP_MULTICAST_IF2 = 0x1F,
189
  CPNET_IP_MULTICAST_LOOP = 0x12,
190
  CPNET_IP_TOS = 0x03,
191
  CPNET_IP_TTL = 0x1E61
192
};
193
 
194
 
195
/*
196
 * Class:     gnu_java_net_VMPlainSocketImpl
197
 * Method:    setOption
198
 * Signature: (III)V
199
 */
200
JNIEXPORT void JNICALL
201
Java_gnu_java_net_VMPlainSocketImpl_setOption (JNIEnv *env,
202
                                               jclass c __attribute__((unused)),
203
                                               jint fd, jint option, jint value)
204
{
205
  enum java_sockopt joption = (enum java_sockopt) option;
206
  int optname = -1;
207
  int level = SOL_SOCKET;
208
  const int _value = value;
209
  struct linger _linger;
210
  struct timeval _timeo;
211
  void *optval = (void *) &_value;
212
  socklen_t optlen = sizeof (int);
213
 
214
  switch (joption)
215
    {
216
    case CPNET_IP_MULTICAST_LOOP:
217
      level = IPPROTO_IP;
218
      optname = IP_MULTICAST_LOOP;
219
      break;
220
 
221
    case CPNET_SO_KEEPALIVE:
222
      optname = SO_KEEPALIVE;
223
      break;
224
 
225
    case CPNET_SO_LINGER:
226
      optname = SO_LINGER;
227
      if (_value == -1)
228
        _linger.l_onoff = 0;
229
      else
230
        _linger.l_onoff = 1;
231
      _linger.l_linger = _value;
232
      optval = &_linger;
233
      optlen = sizeof (struct linger);
234
      break;
235
 
236
    case CPNET_SO_TIMEOUT:
237
      optname = SO_RCVTIMEO;
238
      _timeo.tv_sec = value / 1000;
239
      _timeo.tv_usec = (value % 1000) * 1000;
240
      optval = &_timeo;
241
      optlen = sizeof (struct timeval);
242
      break;
243
 
244
    case CPNET_SO_SNDBUF:
245
      optname = SO_SNDBUF;
246
      break;
247
 
248
    case CPNET_SO_RCVBUF:
249
      optname = SO_RCVBUF;
250
      break;
251
 
252
    case CPNET_SO_REUSEADDR:
253
      optname = SO_REUSEADDR;
254
      break;
255
 
256
    case CPNET_SO_BROADCAST:
257
      optname = SO_BROADCAST;
258
      break;
259
 
260
    case CPNET_SO_OOBINLINE:
261
      optname = SO_OOBINLINE;
262
      break;
263
 
264
    case CPNET_TCP_NODELAY:
265
      level = IPPROTO_TCP;
266
      optname = TCP_NODELAY;
267
      break;
268
 
269
    case CPNET_IP_TOS:
270
      level = IPPROTO_IP;
271
      optname = IP_TOS;
272
      break;
273
 
274
    case CPNET_IP_TTL:
275
      level = IPPROTO_IP;
276
      optname = IP_TTL;
277
      break;
278
 
279
    case CPNET_SO_BINDADDR:
280
    case CPNET_IP_MULTICAST_IF:
281
    case CPNET_IP_MULTICAST_IF2:
282
      JCL_ThrowException (env, IO_EXCEPTION, "argument not a boolean or integer option");
283
      return;
284
    }
285
 
286
  if (setsockopt (fd, level, optname, (const void *) optval, optlen) == -1)
287
    JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
288
}
289
 
290
/*
291
 * Class:     gnu_java_net_VMPlainSocketImpl
292
 * Method:    getOption
293
 * Signature: (II)I
294
 */
295
JNIEXPORT jint JNICALL
296
Java_gnu_java_net_VMPlainSocketImpl_getOption (JNIEnv *env,
297
                                               jclass c __attribute__((unused)),
298
                                               jint fd, jint option)
299
{
300
  enum java_sockopt joption = (enum java_sockopt) option;
301
  int optname = -1;
302
  int level = SOL_SOCKET;
303
  int value;
304
  struct linger linger;
305
  struct timeval timeo;
306
  void *optval = &value;
307
  socklen_t optlen = sizeof (int);
308
 
309
  switch (joption)
310
    {
311
    case CPNET_IP_MULTICAST_LOOP:
312
      level = IPPROTO_IP;
313
      optname = IP_MULTICAST_LOOP;
314
      break;
315
 
316
    case CPNET_SO_KEEPALIVE:
317
      optname = SO_KEEPALIVE;
318
      break;
319
 
320
    case CPNET_SO_LINGER:
321
      optname = SO_LINGER;
322
      optval = &linger;
323
      optlen = sizeof (struct linger);
324
      break;
325
 
326
    case CPNET_SO_TIMEOUT:
327
      optname = SO_RCVTIMEO;
328
      optval = &timeo;
329
      optlen = sizeof (struct timeval);
330
      break;
331
 
332
    case CPNET_SO_SNDBUF:
333
      optname = SO_SNDBUF;
334
      break;
335
 
336
    case CPNET_SO_RCVBUF:
337
      optname = SO_RCVBUF;
338
      break;
339
 
340
    case CPNET_SO_REUSEADDR:
341
      optname = SO_REUSEADDR;
342
      break;
343
 
344
    case CPNET_SO_BROADCAST:
345
      optname = SO_BROADCAST;
346
      break;
347
 
348
    case CPNET_SO_OOBINLINE:
349
      optname = SO_OOBINLINE;
350
      break;
351
 
352
    case CPNET_TCP_NODELAY:
353
      level = IPPROTO_TCP;
354
      optname = TCP_NODELAY;
355
      break;
356
 
357
    case CPNET_IP_TOS:
358
      level = IPPROTO_IP;
359
      optname = IP_TOS;
360
      break;
361
 
362
    case CPNET_IP_TTL:
363
      level = IPPROTO_IP;
364
      optname = IP_TTL;
365
      break;
366
 
367
    case CPNET_SO_BINDADDR:
368
    case CPNET_IP_MULTICAST_IF:
369
    case CPNET_IP_MULTICAST_IF2:
370
      JCL_ThrowException (env, IO_EXCEPTION, "argument not a boolean or integer option");
371
      return -1;
372
    }
373
 
374
  if (getsockopt (fd, level, optname, optval, &optlen) == -1)
375
    JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
376
 
377
  /* Returns the linger value if it is enabled or -1 in case
378
   * it is disabled. This is how the Java API expects it.
379
   */
380
  if (joption == CPNET_SO_LINGER)
381
    return (linger.l_onoff) ? linger.l_linger : -1;
382
  if (joption == CPNET_SO_TIMEOUT)
383
    return (timeo.tv_sec * 1000) + (timeo.tv_usec / 1000);
384
 
385
  return value;
386
}
387
 
388
JNIEXPORT void JNICALL
389
Java_gnu_java_net_VMPlainSocketImpl_setMulticastInterface (JNIEnv *env,
390
                                                           jclass c __attribute__((unused)),
391
                                                           jint fd,
392
                                                           jint optionId __attribute__((unused)),
393
                                                           jobject addr)
394
{
395
  int result;
396
  cpnet_address *cpaddr = _javanet_get_ip_netaddr (env, addr);
397
 
398
  if ((*env)->ExceptionOccurred (env))
399
    return;
400
 
401
  result = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
402
                      (struct sockaddr *) cpaddr->data, cpaddr->len);
403
 
404
  cpnet_freeAddress (env, cpaddr);
405
 
406
  if (result == -1)
407
    JCL_ThrowException (env, SOCKET_EXCEPTION, cpnative_getErrorString (errno));
408
}
409
 
410
JNIEXPORT void JNICALL
411
Java_gnu_java_net_VMPlainSocketImpl_setMulticastInterface6 (JNIEnv *env,
412
                                                           jclass c __attribute__((unused)),
413
                                                           jint fd,
414
                                                           jint optionId __attribute__((unused)),
415
                                                           jstring ifname)
416
{
417
#ifdef HAVE_SETSOCKOPT
418
#ifdef HAVE_INET6       
419
  int result;
420
  const char *str_ifname = JCL_jstring_to_cstring (env, ifname);
421
  unsigned int if_index;
422
 
423
  if ((*env)->ExceptionOccurred (env))
424
    {
425
      JCL_free_cstring(env, ifname, str_ifname);
426
      return;
427
    }
428
 
429
  if_index = if_nametoindex(str_ifname);
430
  if (!if_index)
431
    {
432
      JCL_free_cstring(env, ifname, str_ifname);
433
      JCL_ThrowException (env, SOCKET_EXCEPTION, "interface does not exist");
434
      return;
435
    }
436
 
437
  result = setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
438
                      (unsigned int *) &if_index, sizeof(if_index));
439
 
440
  JCL_free_cstring(env, ifname, str_ifname);
441
 
442
  if (result == -1)
443
    JCL_ThrowException (env, SOCKET_EXCEPTION, cpnative_getErrorString (errno));
444
#else
445
  (void) fd;
446
  JCL_ThrowException (env, "java/lang/InternalError",
447
                      "IPv6 support not available");
448
#endif /* HAVE_INET6 */
449
#else
450
  (void) fd;
451
  THROW_NO_IPV6(env);
452
#endif /* HAVE_SETSOCKOPT */
453
}
454
 
455
JNIEXPORT jobject JNICALL
456
Java_gnu_java_net_VMPlainSocketImpl_getMulticastInterface (JNIEnv *env,
457
                                                           jclass c __attribute__((unused)),
458
                                                           jint fd,
459
                                                           jint optionId __attribute__((unused)))
460
{
461
  jobject obj;
462
  cpnet_address *cpaddr;
463
  int result = cpnet_getMulticastIF (env, fd, &cpaddr);
464
 
465
  if (result != CPNATIVE_OK)
466
    {
467
      JCL_ThrowException (env, SOCKET_EXCEPTION,
468
                          cpnative_getErrorString (result));
469
      return (0);
470
    }
471
 
472
  obj = _javanet_create_inetaddress (env, cpaddr);
473
  cpnet_freeAddress (env, cpaddr);
474
 
475
  return obj;
476
}
477
 
478
 
479
/*
480
 * Class:     gnu_java_net_VMPlainSocketImpl
481
 * Method:    shutdownInput
482
 * Signature: (I)V
483
 */
484
JNIEXPORT void JNICALL
485
Java_gnu_java_net_VMPlainSocketImpl_shutdownInput (JNIEnv *env,
486
                                                   jclass c __attribute__((unused)),
487
                                                   jint fd)
488
{
489
  if (shutdown (fd, SHUT_RD) == -1)
490
    JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
491
}
492
 
493
/*
494
 * Class:     gnu_java_net_VMPlainSocketImpl
495
 * Method:    shutdownOutput
496
 * Signature: (I)V
497
 */
498
JNIEXPORT void JNICALL
499
Java_gnu_java_net_VMPlainSocketImpl_shutdownOutput (JNIEnv *env,
500
                                                    jclass c __attribute__((unused)),
501
                                                    jint fd)
502
{
503
  if (shutdown (fd, SHUT_WR) == -1)
504
    JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
505
}
506
 
507
 
508
/*
509
 * Class:     gnu_java_net_VMPlainSocketImpl
510
 * Method:    sendUrgentData
511
 * Signature: (II)V
512
 */
513
JNIEXPORT void JNICALL
514
Java_gnu_java_net_VMPlainSocketImpl_sendUrgentData (JNIEnv *env,
515
                                                    jclass c __attribute__((unused)),
516
                                                    jint fd, jint data)
517
{
518
  const char x = (char) data;
519
 
520
  if (send (fd, &x, 1, MSG_OOB) == -1)
521
    JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
522
}
523
 
524
 
525
/*
526
 * Class:     gnu_java_net_VMPlainSocketImpl
527
 * Method:    join
528
 * Signature: (I[B)V
529
 */
530
JNIEXPORT void JNICALL
531
Java_gnu_java_net_VMPlainSocketImpl_join (JNIEnv *env,
532
                                          jclass clazz __attribute__((unused)),
533
                                          jint fd, jbyteArray addr)
534
{
535
#ifdef HAVE_SETSOCKOPT
536
  struct ip_mreq maddr;
537
  jbyte *addr_elems;
538
 
539
  addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
540
  if (addr_elems == NULL)
541
    return;
542
 
543
  maddr.imr_multiaddr.s_addr = * ((uint32_t *) addr_elems);
544
  maddr.imr_interface.s_addr = INADDR_ANY;
545
 
546
  (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
547
 
548
  if (-1 == setsockopt (fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
549
                        &maddr, sizeof (struct ip_mreq)))
550
    JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
551
#else
552
  (void) fd;
553
  (void) addr;
554
  JCL_ThrowException (env, "java/lang/InternalError",
555
                      "socket options not supported");
556
#endif /* HAVE_SETSOCKOPT */
557
}
558
 
559
 
560
/*
561
 * Class:     gnu_java_net_VMPlainSocketImpl
562
 * Method:    join6
563
 * Signature: (I[B)V
564
 */
565
JNIEXPORT void JNICALL
566
Java_gnu_java_net_VMPlainSocketImpl_join6 (JNIEnv *env,
567
                                           jclass clazz __attribute__((unused)),
568
                                           jint fd, jbyteArray addr)
569
{
570
#ifdef HAVE_SETSOCKOPT
571
#ifdef HAVE_INET6
572
  struct ipv6_mreq maddr;
573
  jbyte *addr_elems;
574
 
575
  addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
576
  if (addr_elems == NULL)
577
    return;
578
 
579
  memcpy (&(maddr.ipv6mr_multiaddr.s6_addr), addr_elems, 16);
580
  maddr.ipv6mr_interface = 0;
581
 
582
  (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
583
 
584
  if (-1 == setsockopt (fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
585
                        &maddr, sizeof (struct ipv6_mreq)))
586
    JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
587
#else
588
  (void) fd;
589
  (void) addr;
590
  THROW_NO_IPV6(env);
591
#endif /* HAVE_INET6 */
592
#else
593
  (void) fd;
594
  (void) addr;
595
  JCL_ThrowException (env, "java/lang/InternalError",
596
                      "socket options not supported");
597
#endif /* HAVE_SETSOCKOPT */
598
}
599
 
600
/*
601
 * Class:     gnu_java_net_VMPlainSocketImpl
602
 * Method:    leave
603
 * Signature: (I[B)V
604
 */
605
JNIEXPORT void JNICALL
606
Java_gnu_java_net_VMPlainSocketImpl_leave (JNIEnv *env,
607
                                           jclass c __attribute__((unused)),
608
                                           jint fd, jbyteArray addr)
609
{
610
#ifdef HAVE_SETSOCKOPT
611
  struct ip_mreq maddr;
612
  jbyte *addr_elems;
613
 
614
  addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
615
  if (addr_elems == NULL)
616
    return;
617
 
618
  maddr.imr_multiaddr.s_addr = * ((uint32_t *) addr_elems);
619
  maddr.imr_interface.s_addr = INADDR_ANY;
620
 
621
  (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
622
 
623
  if (-1 == setsockopt (fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
624
                        &maddr, sizeof (struct ip_mreq)))
625
    JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
626
#else
627
  (void) fd;
628
  (void) addr;
629
  JCL_ThrowException (env, "java/lang/InternalError",
630
                      "socket options not supported");
631
#endif /* HAVE_SETSOCKOPT */
632
}
633
 
634
/*
635
 * Class:     gnu_java_net_VMPlainSocketImpl
636
 * Method:    leave6
637
 * Signature: (I[B)V
638
 */
639
JNIEXPORT void JNICALL
640
Java_gnu_java_net_VMPlainSocketImpl_leave6 (JNIEnv *env,
641
                                            jclass c __attribute__((unused)),
642
                                            jint fd, jbyteArray addr)
643
{
644
#ifdef HAVE_SETSOCKOPT
645
#ifdef HAVE_INET6
646
  struct ipv6_mreq maddr;
647
  jbyte *addr_elems;
648
 
649
  addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
650
  if (addr_elems == NULL)
651
    return;
652
 
653
  memcpy (&(maddr.ipv6mr_multiaddr.s6_addr), addr_elems, 16);
654
  maddr.ipv6mr_interface = 0;
655
 
656
  (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
657
 
658
  if (-1 == setsockopt (fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
659
                        &maddr, sizeof (struct ipv6_mreq)))
660
    JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
661
#else
662
  (void) fd;
663
  (void) addr;
664
  THROW_NO_IPV6(env);
665
#endif /* HAVE_INET6 */
666
#else
667
  (void) fd;
668
  (void) addr;
669
  JCL_ThrowException (env, "java/lang/InternalError",
670
                      "socket options not supported");
671
#endif /* HAVE_SETSOCKOPT */
672
}
673
 
674
static uint32_t getif_address (JNIEnv *env, const char *ifname);
675
static int getif_index (JNIEnv *env, const char *ifname);
676
 
677
/*
678
 * Class:     gnu_java_net_VMPlainSocketImpl
679
 * Method:    joinGroup
680
 * Signature: (I[BILjava/lang/String;)V
681
 */
682
JNIEXPORT void JNICALL
683
Java_gnu_java_net_VMPlainSocketImpl_joinGroup (JNIEnv *env,
684
                                               jclass c __attribute__((unused)),
685
                                               jint fd, jbyteArray addr,
686
                                               jstring ifname)
687
{
688
#ifdef HAVE_SETSOCKOPT
689
  struct ip_mreq maddr;
690
  jbyte *addr_elems;
691
  const char *str_ifname;
692
 
693
  if (ifname != NULL)
694
    {
695
      str_ifname = JCL_jstring_to_cstring(env, ifname);
696
      maddr.imr_interface.s_addr = getif_address (env, str_ifname);
697
      JCL_free_cstring(env, ifname, str_ifname);
698
 
699
      if ((*env)->ExceptionCheck (env))
700
        return;
701
    }
702
  else
703
    maddr.imr_interface.s_addr = INADDR_ANY;
704
 
705
  addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
706
  if (addr_elems == NULL)
707
    return;
708
 
709
  maddr.imr_multiaddr.s_addr = * ((uint32_t *) addr_elems);
710
 
711
  (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
712
 
713
  if (-1 == setsockopt (fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
714
                        &maddr, sizeof (struct ip_mreq)))
715
    JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
716
 
717
#else
718
  (void) fd;
719
  (void) addr;
720
  (void) ifname;
721
  JCL_ThrowException (env, "java/lang/InternalError",
722
                      "socket options not supported");
723
#endif /* HAVE_SETSOCKOPT */
724
}
725
 
726
/*
727
 * Class:     gnu_java_net_VMPlainSocketImpl
728
 * Method:    joinGroup6
729
 * Signature: (I[BILjava/lang/String;)V
730
 */
731
JNIEXPORT void JNICALL
732
Java_gnu_java_net_VMPlainSocketImpl_joinGroup6 (JNIEnv *env,
733
                                                jclass c __attribute__((unused)),
734
                                                jint fd, jbyteArray addr,
735
                                                jstring ifname)
736
{
737
#ifdef HAVE_SETSOCKOPT
738
#ifdef HAVE_INET6
739
  struct ipv6_mreq maddr;
740
  jbyte *addr_elems;
741
  const char *str_ifname;
742
 
743
  if (ifname == NULL)
744
    {
745
      str_ifname = JCL_jstring_to_cstring(env, ifname);
746
      maddr.ipv6mr_interface = getif_index (env, str_ifname);
747
      JCL_free_cstring(env, ifname, str_ifname);
748
 
749
      if ((*env)->ExceptionCheck (env))
750
        return;
751
    }
752
  else
753
    maddr.ipv6mr_interface = 0;
754
 
755
  addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
756
  if (addr_elems == NULL)
757
    return;
758
 
759
  memcpy (&(maddr.ipv6mr_multiaddr.s6_addr), addr_elems, 16);
760
 
761
  (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
762
 
763
  if (-1 == setsockopt (fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
764
                        &maddr, sizeof (struct ipv6_mreq)))
765
    JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
766
#else
767
  (void) fd;
768
  (void) addr;
769
  THROW_NO_IPV6(env);
770
#endif /* HAVE_INET6 */
771
#else
772
  (void) fd;
773
  (void) addr;
774
  JCL_ThrowException (env, "java/lang/InternalError",
775
                      "socket options not supported");
776
#endif /* HAVE_SETSOCKOPT */
777
}
778
 
779
/*
780
 * Class:     gnu_java_net_VMPlainSocketImpl
781
 * Method:    leaveGroup
782
 * Signature: (I[BILjava/lang/String;)V
783
 */
784
JNIEXPORT void JNICALL
785
Java_gnu_java_net_VMPlainSocketImpl_leaveGroup (JNIEnv *env,
786
                                                jclass c __attribute__((unused)),
787
                                                jint fd, jbyteArray addr,
788
                                                jstring ifname)
789
{
790
#ifdef HAVE_SETSOCKOPT
791
  struct ip_mreq maddr;
792
  jbyte *addr_elems;
793
  const char *str_ifname;
794
 
795
  if (ifname != NULL)
796
    {
797
      str_ifname = JCL_jstring_to_cstring(env, ifname);
798
      maddr.imr_interface.s_addr = getif_address (env, str_ifname);
799
      JCL_free_cstring(env, ifname, str_ifname);
800
 
801
      if ((*env)->ExceptionCheck (env))
802
        return;
803
    }
804
  else
805
    maddr.imr_interface.s_addr = INADDR_ANY;
806
 
807
  addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
808
  if (addr_elems == NULL)
809
    return;
810
 
811
  maddr.imr_multiaddr.s_addr = * ((uint32_t *) addr_elems);
812
 
813
  (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
814
 
815
  if (-1 == setsockopt (fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
816
                        &maddr, sizeof (struct ip_mreq)))
817
    JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
818
#else
819
  (void) fd;
820
  (void) addr;
821
  (void) ifname;
822
  JCL_ThrowException (env, "java/lang/InternalError",
823
                      "socket options not supported");
824
#endif /* HAVE_SETSOCKOPT */
825
}
826
 
827
/*
828
 * Class:     gnu_java_net_VMPlainSocketImpl
829
 * Method:    leaveGroup6
830
 * Signature: (I[BILjava/lang/String;)V
831
 */
832
JNIEXPORT void JNICALL
833
Java_gnu_java_net_VMPlainSocketImpl_leaveGroup6 (JNIEnv *env,
834
                                                jclass c __attribute__((unused)),
835
                                                jint fd, jbyteArray addr,
836
                                                jstring ifname)
837
{
838
#ifdef HAVE_SETSOCKOPT
839
#ifdef HAVE_INET6
840
  struct ipv6_mreq maddr;
841
  jbyte *addr_elems;
842
  const char *str_ifname;
843
 
844
  if (ifname == NULL)
845
    {
846
      str_ifname = JCL_jstring_to_cstring(env, ifname);
847
      maddr.ipv6mr_interface = getif_index (env, str_ifname);
848
      JCL_free_cstring(env, ifname, str_ifname);
849
 
850
      if ((*env)->ExceptionCheck (env))
851
        return;
852
    }
853
  else
854
    maddr.ipv6mr_interface = 0;
855
 
856
  addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
857
  if (addr_elems == NULL)
858
    return;
859
 
860
  memcpy (&(maddr.ipv6mr_multiaddr.s6_addr), addr_elems, 16);
861
 
862
  (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
863
 
864
  if (-1 == setsockopt (fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
865
                        &maddr, sizeof (struct ipv6_mreq)))
866
    JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
867
#else
868
  (void) fd;
869
  (void) addr;
870
  THROW_NO_IPV6(env);
871
#endif /* HAVE_INET6 */
872
#else
873
  (void) fd;
874
  (void) addr;
875
  JCL_ThrowException (env, "java/lang/InternalError",
876
                      "socket options not supported");
877
#endif /* HAVE_SETSOCKOPT */
878
}
879
 
880
static uint32_t
881
getif_address (JNIEnv *env, const char *ifname)
882
{
883
#if defined (HAVE_IFADDRS_H) && defined (HAVE_GETIFADDRS)
884
  struct ifaddrs *ifaddrs, *i;
885
  uint32_t addr = 0;
886
  int foundaddr = 0;
887
 
888
  if (getifaddrs (&ifaddrs) == -1)
889
    {
890
      JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
891
      return 0;
892
    }
893
 
894
  for (i = ifaddrs; i != NULL; i = i->ifa_next)
895
    {
896
      if (strcmp (ifname, i->ifa_name) == 0)
897
        {
898
          /* Matched the name; see if there is an IPv4 address. */
899
          if (i->ifa_addr->sa_family == AF_INET)
900
            {
901
              foundaddr = 1;
902
              addr = ((struct sockaddr_in *) i->ifa_addr)->sin_addr.s_addr;
903
              break;
904
            }
905
        }
906
    }
907
 
908
  if (!foundaddr)
909
    JCL_ThrowException (env, SOCKET_EXCEPTION, "interface has no IPv4 address");
910
 
911
  freeifaddrs (ifaddrs);
912
 
913
  return addr;
914
#else
915
  (void) ifname;
916
  JCL_ThrowException (env, "java/lang/InternalError",
917
                      "getifaddrs not available");
918
  return 0;
919
#endif /* HAVE_IFADDRS_H && HAVE_GETIFADDRS */
920
}
921
 
922
static int
923
getif_index (JNIEnv *env, const char *ifname)
924
{
925
#if defined (HAVE_IFADDRS_H) && defined (HAVE_GETIFADDRS)
926
  struct ifaddrs *ifaddrs, *i;
927
  char *lastname = NULL;
928
  int index = 1;
929
  int foundname = 0;
930
 
931
  if (getifaddrs (&ifaddrs) == -1)
932
    {
933
      JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
934
      return -1;
935
    }
936
 
937
  lastname = ifaddrs->ifa_name;
938
  for (i = ifaddrs; i != NULL; i = i->ifa_next)
939
    {
940
      if (strcmp (lastname, ifaddrs->ifa_name) != 0)
941
        {
942
          lastname = ifaddrs->ifa_name;
943
          index++;
944
        }
945
      if (strcmp (ifname, ifaddrs->ifa_name) == 0)
946
        {
947
          foundname = 1;
948
          break;
949
        }
950
    }
951
 
952
  if (!foundname)
953
    JCL_ThrowException (env, SOCKET_EXCEPTION,
954
                        "no interface with that name");
955
 
956
  freeifaddrs (ifaddrs);
957
 
958
  return index;
959
#else
960
  (void) ifname;
961
  JCL_ThrowException (env, "java/lang/InternalError",
962
                      "getifaddrs not available");
963
  return -1;
964
#endif /* HAVE_GETIFADDRS */
965
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.