1566 
1567                         len = udp->udp_recv_ipp.ipp_ipv4_options_len;
1568                         ASSERT(len != 0);
1569                         bcopy(udp->udp_recv_ipp.ipp_ipv4_options, ptr, len);
1570                         mutex_exit(&connp->conn_lock);
1571                         return (len);
1572                 }
1573                 break;
1574         case IPPROTO_UDP:
1575                 switch (name) {
1576                 case UDP_NAT_T_ENDPOINT:
1577                         mutex_enter(&connp->conn_lock);
1578                         *i1 = udp->udp_nat_t_endpoint;
1579                         mutex_exit(&connp->conn_lock);
1580                         return (sizeof (int));
1581                 case UDP_RCVHDR:
1582                         mutex_enter(&connp->conn_lock);
1583                         *i1 = udp->udp_rcvhdr ? 1 : 0;
1584                         mutex_exit(&connp->conn_lock);
1585                         return (sizeof (int));
1586                 }
1587         }
1588         mutex_enter(&connp->conn_lock);
1589         retval = conn_opt_get(&coas, level, name, ptr);
1590         mutex_exit(&connp->conn_lock);
1591         return (retval);
1592 }
1593 
1594 /*
1595  * This routine retrieves the current status of socket options.
1596  * It returns the size of the option retrieved, or -1.
1597  */
1598 int
1599 udp_tpi_opt_get(queue_t *q, t_scalar_t level, t_scalar_t name, uchar_t *ptr)
1600 {
1601         conn_t          *connp = Q_TO_CONN(q);
1602         int             err;
1603 
1604         err = udp_opt_get(connp, level, name, ptr);
1605         return (err);
 
1701                          * to IPv6.
1702                          */
1703                         if (connp->conn_family != AF_INET) {
1704                                 return (EAFNOSUPPORT);
1705                         }
1706 
1707                         if (!checkonly) {
1708                                 mutex_enter(&connp->conn_lock);
1709                                 udp->udp_nat_t_endpoint = onoff;
1710                                 mutex_exit(&connp->conn_lock);
1711                                 coa->coa_changed |= COA_HEADER_CHANGED;
1712                                 coa->coa_changed |= COA_WROFF_CHANGED;
1713                         }
1714                         /* Fully handled this option. */
1715                         return (0);
1716                 case UDP_RCVHDR:
1717                         mutex_enter(&connp->conn_lock);
1718                         udp->udp_rcvhdr = onoff;
1719                         mutex_exit(&connp->conn_lock);
1720                         return (0);
1721                 }
1722                 break;
1723         }
1724         error = conn_opt_set(coa, level, name, inlen, invalp,
1725             checkonly, cr);
1726         return (error);
1727 }
1728 
1729 /*
1730  * This routine sets socket options.
1731  */
1732 int
1733 udp_opt_set(conn_t *connp, uint_t optset_context, int level,
1734     int name, uint_t inlen, uchar_t *invalp, uint_t *outlenp,
1735     uchar_t *outvalp, void *thisdg_attrs, cred_t *cr)
1736 {
1737         udp_t           *udp = connp->conn_udp;
1738         int             err;
1739         conn_opt_arg_t  coas, *coa;
1740         boolean_t       checkonly;
 
5893                  */
5894                 udp->udp_state = TS_IDLE;
5895         }
5896         return (error);
5897 }
5898 
5899 int
5900 udp_send(sock_lower_handle_t proto_handle, mblk_t *mp, struct nmsghdr *msg,
5901     cred_t *cr)
5902 {
5903         sin6_t          *sin6;
5904         sin_t           *sin = NULL;
5905         uint_t          srcid;
5906         conn_t          *connp = (conn_t *)proto_handle;
5907         udp_t           *udp = connp->conn_udp;
5908         int             error = 0;
5909         udp_stack_t     *us = udp->udp_us;
5910         ushort_t        ipversion;
5911         pid_t           pid = curproc->p_pid;
5912         ip_xmit_attr_t  *ixa;
5913 
5914         ASSERT(DB_TYPE(mp) == M_DATA);
5915 
5916         /* All Solaris components should pass a cred for this operation. */
5917         ASSERT(cr != NULL);
5918 
5919         /* do an implicit bind if necessary */
5920         if (udp->udp_state == TS_UNBND) {
5921                 error = udp_implicit_bind(connp, cr);
5922                 /*
5923                  * We could be racing with an actual bind, in which case
5924                  * we would see EPROTO. We cross our fingers and try
5925                  * to connect.
5926                  */
5927                 if (!(error == 0 || error == EPROTO)) {
5928                         freemsg(mp);
5929                         return (error);
5930                 }
5931         }
5932 
5933         /* Connected? */
5934         if (msg->msg_name == NULL) {
5935                 if (udp->udp_state != TS_DATA_XFER) {
5936                         UDPS_BUMP_MIB(us, udpOutErrors);
5937                         return (EDESTADDRREQ);
5938                 }
5939                 if (msg->msg_controllen != 0) {
5940                         error = udp_output_ancillary(connp, NULL, NULL, mp,
5941                             NULL, msg, cr, pid);
5942                 } else {
5943                         error = udp_output_connected(connp, mp, cr, pid);
5944                 }
5945                 if (us->us_sendto_ignerr)
5946                         return (0);
5947                 else
5948                         return (error);
5949         }
5950         if (udp->udp_state == TS_DATA_XFER) {
5951                 UDPS_BUMP_MIB(us, udpOutErrors);
5952                 return (EISCONN);
5953         }
5954         error = proto_verify_ip_addr(connp->conn_family,
5955             (struct sockaddr *)msg->msg_name, msg->msg_namelen);
5956         if (error != 0) {
5957                 UDPS_BUMP_MIB(us, udpOutErrors);
5958                 return (error);
5959         }
5960         switch (connp->conn_family) {
5961         case AF_INET6:
5962                 sin6 = (sin6_t *)msg->msg_name;
5963 
5964                 srcid = sin6->__sin6_src_id;
5965 
5966                 if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
5967                         /*
5968                          * Destination is a non-IPv4-compatible IPv6 address.
5969                          * Send out an IPv6 format packet.
5970                          */
5971 
5972                         /*
5973                          * If the local address is a mapped address return
 
 | 
 
 
1566 
1567                         len = udp->udp_recv_ipp.ipp_ipv4_options_len;
1568                         ASSERT(len != 0);
1569                         bcopy(udp->udp_recv_ipp.ipp_ipv4_options, ptr, len);
1570                         mutex_exit(&connp->conn_lock);
1571                         return (len);
1572                 }
1573                 break;
1574         case IPPROTO_UDP:
1575                 switch (name) {
1576                 case UDP_NAT_T_ENDPOINT:
1577                         mutex_enter(&connp->conn_lock);
1578                         *i1 = udp->udp_nat_t_endpoint;
1579                         mutex_exit(&connp->conn_lock);
1580                         return (sizeof (int));
1581                 case UDP_RCVHDR:
1582                         mutex_enter(&connp->conn_lock);
1583                         *i1 = udp->udp_rcvhdr ? 1 : 0;
1584                         mutex_exit(&connp->conn_lock);
1585                         return (sizeof (int));
1586                 case UDP_SND_TO_CONNECTED:
1587                         mutex_enter(&connp->conn_lock);
1588                         *i1 = udp->udp_snd_to_conn ? 1 : 0;
1589                         mutex_exit(&connp->conn_lock);
1590                         return (sizeof (int));
1591                 }
1592         }
1593         mutex_enter(&connp->conn_lock);
1594         retval = conn_opt_get(&coas, level, name, ptr);
1595         mutex_exit(&connp->conn_lock);
1596         return (retval);
1597 }
1598 
1599 /*
1600  * This routine retrieves the current status of socket options.
1601  * It returns the size of the option retrieved, or -1.
1602  */
1603 int
1604 udp_tpi_opt_get(queue_t *q, t_scalar_t level, t_scalar_t name, uchar_t *ptr)
1605 {
1606         conn_t          *connp = Q_TO_CONN(q);
1607         int             err;
1608 
1609         err = udp_opt_get(connp, level, name, ptr);
1610         return (err);
 
1706                          * to IPv6.
1707                          */
1708                         if (connp->conn_family != AF_INET) {
1709                                 return (EAFNOSUPPORT);
1710                         }
1711 
1712                         if (!checkonly) {
1713                                 mutex_enter(&connp->conn_lock);
1714                                 udp->udp_nat_t_endpoint = onoff;
1715                                 mutex_exit(&connp->conn_lock);
1716                                 coa->coa_changed |= COA_HEADER_CHANGED;
1717                                 coa->coa_changed |= COA_WROFF_CHANGED;
1718                         }
1719                         /* Fully handled this option. */
1720                         return (0);
1721                 case UDP_RCVHDR:
1722                         mutex_enter(&connp->conn_lock);
1723                         udp->udp_rcvhdr = onoff;
1724                         mutex_exit(&connp->conn_lock);
1725                         return (0);
1726                 case UDP_SND_TO_CONNECTED:
1727                         mutex_enter(&connp->conn_lock);
1728                         udp->udp_snd_to_conn = onoff;
1729                         mutex_exit(&connp->conn_lock);
1730                         return (0);
1731                 }
1732                 break;
1733         }
1734         error = conn_opt_set(coa, level, name, inlen, invalp,
1735             checkonly, cr);
1736         return (error);
1737 }
1738 
1739 /*
1740  * This routine sets socket options.
1741  */
1742 int
1743 udp_opt_set(conn_t *connp, uint_t optset_context, int level,
1744     int name, uint_t inlen, uchar_t *invalp, uint_t *outlenp,
1745     uchar_t *outvalp, void *thisdg_attrs, cred_t *cr)
1746 {
1747         udp_t           *udp = connp->conn_udp;
1748         int             err;
1749         conn_opt_arg_t  coas, *coa;
1750         boolean_t       checkonly;
 
5903                  */
5904                 udp->udp_state = TS_IDLE;
5905         }
5906         return (error);
5907 }
5908 
5909 int
5910 udp_send(sock_lower_handle_t proto_handle, mblk_t *mp, struct nmsghdr *msg,
5911     cred_t *cr)
5912 {
5913         sin6_t          *sin6;
5914         sin_t           *sin = NULL;
5915         uint_t          srcid;
5916         conn_t          *connp = (conn_t *)proto_handle;
5917         udp_t           *udp = connp->conn_udp;
5918         int             error = 0;
5919         udp_stack_t     *us = udp->udp_us;
5920         ushort_t        ipversion;
5921         pid_t           pid = curproc->p_pid;
5922         ip_xmit_attr_t  *ixa;
5923         boolean_t       snd_to_conn;
5924 
5925         ASSERT(DB_TYPE(mp) == M_DATA);
5926 
5927         /* All Solaris components should pass a cred for this operation. */
5928         ASSERT(cr != NULL);
5929 
5930         /* do an implicit bind if necessary */
5931         if (udp->udp_state == TS_UNBND) {
5932                 error = udp_implicit_bind(connp, cr);
5933                 /*
5934                  * We could be racing with an actual bind, in which case
5935                  * we would see EPROTO. We cross our fingers and try
5936                  * to connect.
5937                  */
5938                 if (!(error == 0 || error == EPROTO)) {
5939                         freemsg(mp);
5940                         return (error);
5941                 }
5942         }
5943 
5944         /* Connected? */
5945         if (msg->msg_name == NULL) {
5946                 if (udp->udp_state != TS_DATA_XFER) {
5947                         UDPS_BUMP_MIB(us, udpOutErrors);
5948                         return (EDESTADDRREQ);
5949                 }
5950                 if (msg->msg_controllen != 0) {
5951                         error = udp_output_ancillary(connp, NULL, NULL, mp,
5952                             NULL, msg, cr, pid);
5953                 } else {
5954                         error = udp_output_connected(connp, mp, cr, pid);
5955                 }
5956                 if (us->us_sendto_ignerr)
5957                         return (0);
5958                 else
5959                         return (error);
5960         }
5961 
5962         /*
5963          * Check if we're allowed to send to a connection on which we've
5964          * already called 'connect'. The posix spec. allows both behaviors but
5965          * historically we've returned an error if already connected. The
5966          * client can allow this via a sockopt.
5967          */
5968         mutex_enter(&connp->conn_lock);
5969         snd_to_conn = (udp->udp_snd_to_conn != 0);
5970         mutex_exit(&connp->conn_lock);
5971         if (udp->udp_state == TS_DATA_XFER && !snd_to_conn) {
5972                 UDPS_BUMP_MIB(us, udpOutErrors);
5973                 return (EISCONN);
5974         }
5975 
5976         error = proto_verify_ip_addr(connp->conn_family,
5977             (struct sockaddr *)msg->msg_name, msg->msg_namelen);
5978         if (error != 0) {
5979                 UDPS_BUMP_MIB(us, udpOutErrors);
5980                 return (error);
5981         }
5982         switch (connp->conn_family) {
5983         case AF_INET6:
5984                 sin6 = (sin6_t *)msg->msg_name;
5985 
5986                 srcid = sin6->__sin6_src_id;
5987 
5988                 if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
5989                         /*
5990                          * Destination is a non-IPv4-compatible IPv6 address.
5991                          * Send out an IPv6 format packet.
5992                          */
5993 
5994                         /*
5995                          * If the local address is a mapped address return
 
 |