979 return 1;
980 }
981
982 /*
983 * Map the Java level socket option to the platform specific
984 * level and option name.
985 */
986 int
987 NET_MapSocketOption(jint cmd, int *level, int *optname) {
988 static struct {
989 jint cmd;
990 int level;
991 int optname;
992 } const opts[] = {
993 { java_net_SocketOptions_TCP_NODELAY, IPPROTO_TCP, TCP_NODELAY },
994 { java_net_SocketOptions_SO_OOBINLINE, SOL_SOCKET, SO_OOBINLINE },
995 { java_net_SocketOptions_SO_LINGER, SOL_SOCKET, SO_LINGER },
996 { java_net_SocketOptions_SO_SNDBUF, SOL_SOCKET, SO_SNDBUF },
997 { java_net_SocketOptions_SO_RCVBUF, SOL_SOCKET, SO_RCVBUF },
998 { java_net_SocketOptions_SO_KEEPALIVE, SOL_SOCKET, SO_KEEPALIVE },
999 #if defined(_AIX)
1000 { java_net_SocketOptions_SO_REUSEADDR, SOL_SOCKET, SO_REUSEPORT },
1001 #else
1002 { java_net_SocketOptions_SO_REUSEADDR, SOL_SOCKET, SO_REUSEADDR },
1003 #endif
1004 { java_net_SocketOptions_SO_BROADCAST, SOL_SOCKET, SO_BROADCAST },
1005 { java_net_SocketOptions_IP_TOS, IPPROTO_IP, IP_TOS },
1006 { java_net_SocketOptions_IP_MULTICAST_IF, IPPROTO_IP, IP_MULTICAST_IF },
1007 { java_net_SocketOptions_IP_MULTICAST_IF2, IPPROTO_IP, IP_MULTICAST_IF },
1008 { java_net_SocketOptions_IP_MULTICAST_LOOP, IPPROTO_IP, IP_MULTICAST_LOOP },
1009 };
1010
1011 int i;
1012
1013 /*
1014 * Different multicast options if IPv6 is enabled
1015 */
1016 #ifdef AF_INET6
1017 if (ipv6_available()) {
1018 switch (cmd) {
1019 case java_net_SocketOptions_IP_MULTICAST_IF:
1020 case java_net_SocketOptions_IP_MULTICAST_IF2:
1021 *level = IPPROTO_IPV6;
1022 *optname = IPV6_MULTICAST_IF;
1023 return 0;
1268 return rv;
1269 }
1270
1271 /*
1272 * Wrapper for setsockopt system routine - performs any
1273 * necessary pre/post processing to deal with OS specific
1274 * issue :-
1275 *
1276 * On Solaris need to limit the suggested value for SO_SNDBUF
1277 * and SO_RCVBUF to the kernel configured limit
1278 *
1279 * For IP_TOS socket option need to mask off bits as this
1280 * aren't automatically masked by the kernel and results in
1281 * an error. In addition IP_TOS is a NOOP with IPv6 as it
1282 * should be setup as connection time.
1283 */
1284 int
1285 NET_SetSockOpt(int fd, int level, int opt, const void *arg,
1286 int len)
1287 {
1288 #ifndef IPTOS_TOS_MASK
1289 #define IPTOS_TOS_MASK 0x1e
1290 #endif
1291 #ifndef IPTOS_PREC_MASK
1292 #define IPTOS_PREC_MASK 0xe0
1293 #endif
1294
1295 #if defined(_ALLBSD_SOURCE)
1296 #if defined(KIPC_MAXSOCKBUF)
1297 int mib[3];
1298 size_t rlen;
1299 #endif
1300
1301 int *bufsize;
1302
1303 #ifdef __APPLE__
1304 static int maxsockbuf = -1;
1305 #else
1306 static long maxsockbuf = -1;
1307 #endif
1308
1309 int addopt;
1310 struct linger *ling;
1311 #endif
1312
1313 /*
1314 * IPPROTO/IP_TOS :-
1315 * 1. IPv6 on Solaris/Mac OS: NOOP and will be set
1316 * in flowinfo field when connecting TCP socket,
1317 * or sending UDP packet.
1318 * 2. IPv6 on Linux: By default Linux ignores flowinfo
1319 * field so enable IPV6_FLOWINFO_SEND so that flowinfo
1320 * will be examined.
1321 * 3. IPv4: set socket option based on ToS and Precedence
1322 * fields (otherwise get invalid argument)
1323 */
1324 if (level == IPPROTO_IP && opt == IP_TOS) {
1325 int *iptos;
1326
1327 #if defined(AF_INET6) && (defined(__solaris__) || defined(MACOSX))
1328 if (ipv6_available()) {
1329 return 0;
1330 }
1462 maxsockbuf = (maxsockbuf/5)*4;
1463 #endif
1464 }
1465 #elif defined(__OpenBSD__)
1466 maxsockbuf = SB_MAX;
1467 #else
1468 maxsockbuf = 64 * 1024; /* XXX: NetBSD */
1469 #endif
1470
1471 bufsize = (int *)arg;
1472 if (*bufsize > maxsockbuf) {
1473 *bufsize = maxsockbuf;
1474 }
1475
1476 if (opt == SO_RCVBUF && *bufsize < 1024) {
1477 *bufsize = 1024;
1478 }
1479
1480 }
1481 }
1482
1483 /*
1484 * On Solaris, SO_REUSEADDR will allow multiple datagram
1485 * sockets to bind to the same port. The network jck tests
1486 * for this "feature", so we need to emulate it by turning on
1487 * SO_REUSEPORT as well for that combination.
1488 */
1489 if (level == SOL_SOCKET && opt == SO_REUSEADDR) {
1490 int sotype;
1491 socklen_t arglen;
1492
1493 arglen = sizeof(sotype);
1494 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype, &arglen) < 0) {
1495 return -1;
1496 }
1497
1498 if (sotype == SOCK_DGRAM) {
1499 addopt = SO_REUSEPORT;
1500 setsockopt(fd, level, addopt, arg, len);
1501 }
1502 }
1503
1504 #endif
1505
1506 return setsockopt(fd, level, opt, arg, len);
1507 }
1508
1509 /*
1510 * Wrapper for bind system call - performs any necessary pre/post
1511 * processing to deal with OS specific issues :-
1512 *
1513 * Linux allows a socket to bind to 127.0.0.255 which must be
1514 * caught.
1515 *
1516 * On Solaris with IPv6 enabled we must use an exclusive
1517 * bind to guarantee a unique port number across the IPv4 and
1518 * IPv6 port spaces.
1519 *
1520 */
1521 int
1522 NET_Bind(int fd, struct sockaddr *him, int len)
1523 {
1653 FD_SET(fd, &rd);
1654 }
1655 if (flags & NET_WAIT_WRITE) {
1656 FD_SET(fd, &wr);
1657 }
1658 if (flags & NET_WAIT_CONNECT) {
1659 FD_SET(fd, &wr);
1660 FD_SET(fd, &ex);
1661 }
1662
1663 errno = 0;
1664 read_rv = NET_Select(fd+1, &rd, &wr, &ex, &t);
1665 }
1666 #endif
1667
1668 newTime = JVM_CurrentTimeMillis(env, 0);
1669 timeout -= (newTime - prevTime);
1670 if (timeout <= 0) {
1671 return read_rv > 0 ? 0 : -1;
1672 }
1673 newTime = prevTime;
1674
1675 if (read_rv > 0) {
1676 break;
1677 }
1678
1679
1680 } /* while */
1681
1682 return timeout;
1683 }
|
979 return 1;
980 }
981
982 /*
983 * Map the Java level socket option to the platform specific
984 * level and option name.
985 */
986 int
987 NET_MapSocketOption(jint cmd, int *level, int *optname) {
988 static struct {
989 jint cmd;
990 int level;
991 int optname;
992 } const opts[] = {
993 { java_net_SocketOptions_TCP_NODELAY, IPPROTO_TCP, TCP_NODELAY },
994 { java_net_SocketOptions_SO_OOBINLINE, SOL_SOCKET, SO_OOBINLINE },
995 { java_net_SocketOptions_SO_LINGER, SOL_SOCKET, SO_LINGER },
996 { java_net_SocketOptions_SO_SNDBUF, SOL_SOCKET, SO_SNDBUF },
997 { java_net_SocketOptions_SO_RCVBUF, SOL_SOCKET, SO_RCVBUF },
998 { java_net_SocketOptions_SO_KEEPALIVE, SOL_SOCKET, SO_KEEPALIVE },
999 { java_net_SocketOptions_SO_REUSEADDR, SOL_SOCKET, SO_REUSEADDR },
1000 { java_net_SocketOptions_SO_BROADCAST, SOL_SOCKET, SO_BROADCAST },
1001 { java_net_SocketOptions_IP_TOS, IPPROTO_IP, IP_TOS },
1002 { java_net_SocketOptions_IP_MULTICAST_IF, IPPROTO_IP, IP_MULTICAST_IF },
1003 { java_net_SocketOptions_IP_MULTICAST_IF2, IPPROTO_IP, IP_MULTICAST_IF },
1004 { java_net_SocketOptions_IP_MULTICAST_LOOP, IPPROTO_IP, IP_MULTICAST_LOOP },
1005 };
1006
1007 int i;
1008
1009 /*
1010 * Different multicast options if IPv6 is enabled
1011 */
1012 #ifdef AF_INET6
1013 if (ipv6_available()) {
1014 switch (cmd) {
1015 case java_net_SocketOptions_IP_MULTICAST_IF:
1016 case java_net_SocketOptions_IP_MULTICAST_IF2:
1017 *level = IPPROTO_IPV6;
1018 *optname = IPV6_MULTICAST_IF;
1019 return 0;
1264 return rv;
1265 }
1266
1267 /*
1268 * Wrapper for setsockopt system routine - performs any
1269 * necessary pre/post processing to deal with OS specific
1270 * issue :-
1271 *
1272 * On Solaris need to limit the suggested value for SO_SNDBUF
1273 * and SO_RCVBUF to the kernel configured limit
1274 *
1275 * For IP_TOS socket option need to mask off bits as this
1276 * aren't automatically masked by the kernel and results in
1277 * an error. In addition IP_TOS is a NOOP with IPv6 as it
1278 * should be setup as connection time.
1279 */
1280 int
1281 NET_SetSockOpt(int fd, int level, int opt, const void *arg,
1282 int len)
1283 {
1284
1285 #ifndef IPTOS_TOS_MASK
1286 #define IPTOS_TOS_MASK 0x1e
1287 #endif
1288 #ifndef IPTOS_PREC_MASK
1289 #define IPTOS_PREC_MASK 0xe0
1290 #endif
1291
1292 #if defined(_ALLBSD_SOURCE)
1293 #if defined(KIPC_MAXSOCKBUF)
1294 int mib[3];
1295 size_t rlen;
1296 #endif
1297
1298 int *bufsize;
1299
1300 #ifdef __APPLE__
1301 static int maxsockbuf = -1;
1302 #else
1303 static long maxsockbuf = -1;
1304 #endif
1305 #endif
1306
1307 /*
1308 * IPPROTO/IP_TOS :-
1309 * 1. IPv6 on Solaris/Mac OS: NOOP and will be set
1310 * in flowinfo field when connecting TCP socket,
1311 * or sending UDP packet.
1312 * 2. IPv6 on Linux: By default Linux ignores flowinfo
1313 * field so enable IPV6_FLOWINFO_SEND so that flowinfo
1314 * will be examined.
1315 * 3. IPv4: set socket option based on ToS and Precedence
1316 * fields (otherwise get invalid argument)
1317 */
1318 if (level == IPPROTO_IP && opt == IP_TOS) {
1319 int *iptos;
1320
1321 #if defined(AF_INET6) && (defined(__solaris__) || defined(MACOSX))
1322 if (ipv6_available()) {
1323 return 0;
1324 }
1456 maxsockbuf = (maxsockbuf/5)*4;
1457 #endif
1458 }
1459 #elif defined(__OpenBSD__)
1460 maxsockbuf = SB_MAX;
1461 #else
1462 maxsockbuf = 64 * 1024; /* XXX: NetBSD */
1463 #endif
1464
1465 bufsize = (int *)arg;
1466 if (*bufsize > maxsockbuf) {
1467 *bufsize = maxsockbuf;
1468 }
1469
1470 if (opt == SO_RCVBUF && *bufsize < 1024) {
1471 *bufsize = 1024;
1472 }
1473
1474 }
1475 }
1476 #endif
1477
1478 #if defined(_ALLBSD_SOURCE) || defined(_AIX)
1479 /*
1480 * On Solaris, SO_REUSEADDR will allow multiple datagram
1481 * sockets to bind to the same port. The network jck tests check
1482 * for this "feature", so we need to emulate it by turning on
1483 * SO_REUSEPORT as well for that combination.
1484 */
1485 if (level == SOL_SOCKET && opt == SO_REUSEADDR) {
1486 int sotype;
1487 socklen_t arglen;
1488
1489 arglen = sizeof(sotype);
1490 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype, &arglen) < 0) {
1491 return -1;
1492 }
1493
1494 if (sotype == SOCK_DGRAM) {
1495 setsockopt(fd, level, SO_REUSEPORT, arg, len);
1496 }
1497 }
1498 #endif
1499
1500 return setsockopt(fd, level, opt, arg, len);
1501 }
1502
1503 /*
1504 * Wrapper for bind system call - performs any necessary pre/post
1505 * processing to deal with OS specific issues :-
1506 *
1507 * Linux allows a socket to bind to 127.0.0.255 which must be
1508 * caught.
1509 *
1510 * On Solaris with IPv6 enabled we must use an exclusive
1511 * bind to guarantee a unique port number across the IPv4 and
1512 * IPv6 port spaces.
1513 *
1514 */
1515 int
1516 NET_Bind(int fd, struct sockaddr *him, int len)
1517 {
1647 FD_SET(fd, &rd);
1648 }
1649 if (flags & NET_WAIT_WRITE) {
1650 FD_SET(fd, &wr);
1651 }
1652 if (flags & NET_WAIT_CONNECT) {
1653 FD_SET(fd, &wr);
1654 FD_SET(fd, &ex);
1655 }
1656
1657 errno = 0;
1658 read_rv = NET_Select(fd+1, &rd, &wr, &ex, &t);
1659 }
1660 #endif
1661
1662 newTime = JVM_CurrentTimeMillis(env, 0);
1663 timeout -= (newTime - prevTime);
1664 if (timeout <= 0) {
1665 return read_rv > 0 ? 0 : -1;
1666 }
1667 prevTime = newTime;
1668
1669 if (read_rv > 0) {
1670 break;
1671 }
1672
1673
1674 } /* while */
1675
1676 return timeout;
1677 }
|