Beispiel #1
0
/* FUNCTION: bsd_getsockopt()
 *
 * Get a socket option value
 *
 * PARAM1: s; IN - socket descriptor 
 * PARAM2: level; IN - the level of the option to get
 * PARAM3: name; IN - the name of the option to get
 * PARAM4: opt; OUT - ptr to buffer for return of option value; may be
 *              NULL
 * PARAM5: optlen; IN/OUT - ptr to int; on entry, specifies the length
 *                 in bytes of opt; on successful return, specifies the
 *                 length of the returned option; may be NULL if opt is
 *                 also NULL
 * RETURNS: 0 if successful, -1 if an error occurred.  The error is
 *          available via bsd_errno(s).
 */
int
bsd_getsockopt(BSD_SOCKET s,
               int level,
               int name,
               void * opt, int * optlen)
{
   struct socket * so;
   int loptlen;
   int e;

   so = LONG2SO(s);
   SOC_CHECK(so);

   /* make sure supplied option value is big enough for the 
    * named option, else fail w/error EFAULT
    */
   loptlen = bsd_i_sockoptlen(level, name);
   if ((optlen == NULL) || (*optlen < loptlen))
   {
      so->so_error = EFAULT;
      return -1;
   }

   e = t_getsockopt(s, level, name, opt, loptlen);

   /* if it worked, copy the option length back for the caller's use */
   if (e == 0)
   {
      *optlen = loptlen;
   }

   return e;
   
}
Beispiel #2
0
int
t_errno(long s)
{
   struct socket *so = LONG2SO(s);
   struct socket *tmp;
   int errcode = ENOTSOCK;

   LOCK_NET_RESOURCE(NET_RESID);    /* protect soq */

   /* search socket queue for passed socket. This routine should
    * not use SOC_CHECK since it can be ifdeffed out, and we must
    * be ready to return EPIPE if the socket does not exist.
    */
   for (tmp = (struct socket *)(&soq); tmp; tmp = tmp->next)
   {
      if (tmp == so)  /* found socket, return error */
      {
         errcode = so->so_error;
         break;
      }
   }

   UNLOCK_NET_RESOURCE(NET_RESID);

   return errcode;
}
Beispiel #3
0
int
t_getsockopt(long s,
   int   level,
   int   name,
   void *   arg,
   int   arglen)

{
   struct socket *   so;
   int   err;

   so = LONG2SO(s);
   SOC_CHECK(so);
   USE_ARG(level);
   USE_ARG(arglen);

   LOCK_NET_RESOURCE (NET_RESID);

   INET_TRACE (INETM_SOCKET,
    ("INET: getsockopt: name %x val %x valsize %d\n",
    name, val));

   /* is it a level IP_OPTIONS call? */
   if (level != IP_OPTIONS)
   {
      if ((err = sogetopt (so, name, arg)) != 0) 
      {
         so->so_error = err;
         UNLOCK_NET_RESOURCE (NET_RESID);
         return SOCKET_ERROR;
      }
   }
   else
   {
      /* level 1 options are for the IP packet level.
       * the info is carried in the socket CB, then put 
       * into the PACKET.
       */
      if (name == IP_TTL_OPT)
      {
         if (!so->so_optsPack) *(int *)arg = IP_TTL;
         else *(int *)arg = (int)so->so_optsPack->ip_ttl;
      }
      else if (name == IP_TOS)
      {
         if (!so->so_optsPack) *(int *)arg = IP_TOS_DEFVAL;
         else *(int *)arg = (int)so->so_optsPack->ip_tos;
      }
      else
      {
         UNLOCK_NET_RESOURCE (NET_RESID);
         return SOCKET_ERROR;
      }
   }   
   so->so_error = 0;

   UNLOCK_NET_RESOURCE (NET_RESID);
   return 0;
}
Beispiel #4
0
/* FUNCTION: bsd_recvfrom()
 *
 * Receive data from a socket
 *
 * PARAM1: s; IN - socket descriptor 
 * PARAM2: buf; OUT - ptr to buffer for return of received data
 * PARAM3: len; IN - length (in bytes) of buf
 * PARAM4: flags; IN - flags to be applied to the recvfrom() operation
 * PARAM5: from; OUT - ptr to buffer for return of sending peer's name;
 *               may be NULL if return of name is not requested
 * PARAM6: fromlen; IN/OUT - ptr to int; on entry, specifies the length
 *                  in bytes of from; on successful return, specifies the
 *                  length of the returned name; may be NULL if 
 *                  from is also NULL
 * RETURNS: the number of bytes received (>= 0), or -1 if an error
 *          occurred.  The error is available via bsd_errno(s).
 */
int
bsd_recvfrom(BSD_SOCKET s,
             void * buf,
             BSD_SIZE_T len,
             int flags,
             struct sockaddr * from, int * fromlen)
{
   struct socket * so;
   struct sockaddr lfrom;
   int lfromlen = 0;
   int lret;

   so = LONG2SO(s);
   SOC_CHECK(so);

   /* if we were given a buffer for the peer's address, also get the
    * buffer's length 
    */
   if (from != NULL)
   {
      if (fromlen == NULL)
      {
         so->so_error = EFAULT;
         return -1;
      }
      lfromlen = *fromlen;
   }

   lret = t_recvfrom(s, (char *)buf, len, flags, &lfrom, &lfromlen );

   /* if we were successful, and we were given a buffer for the peer's
    * name: copy the peer's name back into the buffer, but limit
    * the copy to the lesser of the buffer's length and sizeof(struct
    * sockaddr_in), which is all that t_recvfrom() can return as a peer
    * name.
    * For IPV6 addresses or dual IPV4/IPV6 stack, the max size copied
    * is sizeof(struct sockaddr_in6)
    */
   if ((lret != -1) && (from != NULL))
   {
#ifndef IP_V6
      if (lfromlen > sizeof(struct sockaddr_in))
         lfromlen = sizeof(struct sockaddr_in);
#else
      if (lfromlen > sizeof(struct sockaddr_in6))
         lfromlen = sizeof(struct sockaddr_in6);

#endif
      MEMCPY(from, &lfrom, lfromlen);
      *fromlen = lfromlen;
   }

   return lret;
}
Beispiel #5
0
int
t_recv (long s, 
   char *   buf,
   int   len, 
   int   flag)
{
#ifdef SOCKDEBUG
   char logbuf[10];
#endif
   struct socket *   so;
   int   err;
   int   sendlen = len;

   so = LONG2SO(s);
#ifdef SOC_CHECK_ALWAYS
   SOC_CHECK(so);
#endif
   if ((so->so_state & SO_IO_OK) != SS_ISCONNECTED)
   {
      so->so_error = EPIPE;
#ifdef SOCKDEBUG
      sprintf(logbuf, "t_recv: %d", so->so_error);
      glog_with_type(LOG_TYPE_DEBUG, logbuf, 1);
#endif
      return SOCKET_ERROR;
   }
   so->so_error = 0;

   LOCK_NET_RESOURCE(NET_RESID);
   IN_PROFILER(PF_TCP, PF_ENTRY);        /* measure time in TCP */
   INET_TRACE (INETM_IO, ("INET:recv: so %x, len %d\n", so, len));
   err = soreceive(so, NULL, buf, &len, flag);
   IN_PROFILER(PF_TCP, PF_EXIT);        /* measure time in TCP */
   UNLOCK_NET_RESOURCE(NET_RESID);

   if(err)
   {
      so->so_error = err;
#ifdef SOCKDEBUG
      sprintf(logbuf, "t_recv: %d", so->so_error);
      glog_with_type(LOG_TYPE_DEBUG, logbuf, 1);
#endif
      return SOCKET_ERROR;
   }

   /* return bytes we sent - the amount we wanted to send minus
    * the amount left in the buffer.
    */
   return (sendlen - len);
}
Beispiel #6
0
/* FUNCTION: bsd_getpeername()
 *
 * Get the name of the connected peer
 *
 * PARAM1: s; IN - socket descriptor 
 * PARAM2: name; OUT - ptr to buffer for return of peer's address
 * PARAM3: addrlen; IN/OUT - ptr to int; on entry, specifies the length
 *                  in bytes of name; on successful return, specifies the
 *                  length of the returned name
 * RETURNS: 0 if successful, -1 if an error occurred.  The error is
 *          available via bsd_errno(s).
 */
int
bsd_getpeername(BSD_SOCKET s,
                struct sockaddr * name, int * namelen)
{
   struct socket * so;
   struct sockaddr lname;
   int lnamelen;
   int lret;

   so = LONG2SO(s);
   SOC_CHECK(so);

   /* if the buffer length is bogus, fail */
   if (namelen == NULL)
   {
      so->so_error = EFAULT;
      return -1;
   }
   lnamelen = *namelen;

   lret = t_getpeername(s, &lname, &lnamelen);

   /* if we were successful: copy the peer's address back into the
    * buffer, but limit the copy to the lesser of the buffer's length
    * and sizeof(struct sockaddr_in), which is all that
    * t_getpeername() can return as a peer address, and pass the
    * copied length back to the caller.  
    * For IPV6 addresses, or for dual IPV4/IPV6 stack, 
    * the max size is sizeof(struct sockaddr_in6)
    */
   if (lret != -1)
   {
#ifndef IP_V6
      if (lnamelen > sizeof(struct sockaddr_in))
         lnamelen = sizeof(struct sockaddr_in);
#else
      if (lnamelen > sizeof(struct sockaddr_in6))
         lnamelen = sizeof(struct sockaddr_in6);

#endif
      MEMCPY(name, &lname, lnamelen);
      *namelen = lnamelen;
   }

   return lret;
}
Beispiel #7
0
int
t_bind (long s, 
   struct sockaddr * addr,
   int addrlen)
{
   struct mbuf *     nam;
   struct sockaddr   sa;
   struct sockaddr * sap;
   struct socket *   so;
   int               err;

   so = LONG2SO(s);  /* convert long to socket */
   SOC_CHECK(so);
   DOMAIN_CHECK(so, addrlen);

   so->so_error = 0;
   if (addr == (struct sockaddr *)NULL) 
   {
      MEMSET ((void *)&sa, 0, sizeof(sa));
      addrlen = sizeof(sa);
      sa.sa_family = so->so_domain;
      sap = &sa;
   } else
      sap = addr;

   if ((nam = sockargs (sap, addrlen, MT_SONAME)) == NULL) 
   {
      so->so_error = ENOMEM;
      return SOCKET_ERROR;
   }
   LOCK_NET_RESOURCE(NET_RESID);
   err = sobind (so, nam);
   m_freem(nam);
   UNLOCK_NET_RESOURCE(NET_RESID);
   if (err) 
   {
      so->so_error = err;
      return SOCKET_ERROR;
   }
   return 0;
}
Beispiel #8
0
/* FUNCTION: bsd_accept()
 *
 * Accept a connection on a socket
 *
 * PARAM1: s; IN - socket descriptor for the listening socket
 * PARAM2: addr; OUT - ptr to buffer for return of accepted peer's address;
 *               may be NULL if return of address is not requested
 * PARAM3: addrlen; IN/OUT - ptr to int; on entry, specifies the length
 *                  in bytes of addr; on successful return, specifies the
 *                  length of the returned address; may be NULL if 
 *                  addr is also NULL
 * RETURNS: A socket descriptor if successful, -1 if an error occurred.  
 *          The error is available via bsd_errno(s).
 */
BSD_SOCKET
bsd_accept(BSD_SOCKET s,
           struct sockaddr * addr, int * addrlen)
{
   struct socket * so;
   struct sockaddr laddr;
   long lret;

   so = LONG2SO(s);
   SOC_CHECK(so);

   /* if we were given a buffer for the peer's address, also get the
    * buffer's length 
    */
   if (addr != NULL)
   {
      if (addrlen == 0)
      {
         so->so_error = EFAULT;
         return -1;
      }
   }

   lret = t_accept(s, &laddr, addrlen);

   /* if we were successful, and we were given a buffer for the peer's
    * address: copy the peer's address back into the buffer, but limit
    * the copy to the lesser of the buffer's length and sizeof(struct
    * sockaddr_in), which is all that t_accept() can return as a peer
    * address.  
    */
   if ((lret != -1) && (addr != NULL))
   {
      if (*addrlen > sizeof(struct sockaddr_in))
         *addrlen = sizeof(struct sockaddr_in);
      MEMCPY(addr, &laddr, *addrlen);
   }

   return lret;
}
Beispiel #9
0
int
t_recvfrom(long s, 
   char *   buf,
   int   len, 
   int   flags,
   struct sockaddr * from,
   int * fromlen)
{
   struct socket *   so;
   struct mbuf *     sender = NULL;
   int   err;
   int   sendlen = len;

   so = LONG2SO(s);
   SOC_CHECK(so);
   so->so_error = 0;

   LOCK_NET_RESOURCE(NET_RESID);

   err = soreceive(so, &sender, buf, &len, flags);

   /* copy sender info from mbuf to sockaddr */
   if (sender)
   {
      MEMCPY(from, (mtod(sender, struct sockaddr *)), *fromlen );
      m_freem (sender);
   }

   UNLOCK_NET_RESOURCE(NET_RESID);

   if(err)
   {
      so->so_error = err;
      return SOCKET_ERROR;
   }

   /* OK return: amount of data actually sent */
   return (sendlen - len);
}
Beispiel #10
0
int
t_shutdown(long s, int   how)
{
   struct socket *so;
   int   err;

   so = LONG2SO(s);
   SOC_CHECK(so);
   so->so_error = 0;
   INET_TRACE (INETM_SOCKET, ("INET:shutdown so %x how %d\n", so, how));

   LOCK_NET_RESOURCE(NET_RESID);
   err = soshutdown(so, how);
   UNLOCK_NET_RESOURCE(NET_RESID);

   if (err != 0)
   {
      so->so_error = err;
      return SOCKET_ERROR;
   }
   return 0;
}
Beispiel #11
0
/* FUNCTION: bsd_setsockopt()
 *
 * Set a socket option value
 *
 * PARAM1: s; IN - socket descriptor 
 * PARAM2: level; IN - the level of the option to set
 * PARAM3: name; IN - the name of the option to set
 * PARAM4: opt; OUT - ptr to buffer containing option value; may be
 *              NULL
 * PARAM5: optlen; IN - specifies the length in bytes of the option 
 *                 value in opt
 * RETURNS: 0 if successful, -1 if an error occurred.  The error is
 *          available via bsd_errno(s).
 */
int 
bsd_setsockopt(BSD_SOCKET s,
               int level,
               int name,
               void * opt, int optlen)
{
   struct socket * so;

   so = LONG2SO(s);
   SOC_CHECK(so);

   /* make sure supplied option value is big enough for the 
    * named option, else fail w/error EFAULT
    */
   if (optlen < bsd_i_sockoptlen(level, name))
   {
      so->so_error = EFAULT;
      return -1;
   }

   return t_setsockopt(s, level, name, opt, optlen);
}
Beispiel #12
0
int
t_listen(long s, 
   int   backlog)
{
   struct socket *   so;
   int   err;

   so = LONG2SO(s);  /* convert long to socket */
   SOC_CHECK(so);
   so->so_error = 0;
   INET_TRACE (INETM_SOCKET, ("SOCK:listen:qlen %d\n", backlog));

   LOCK_NET_RESOURCE(NET_RESID);
   err = solisten (so, backlog);
   UNLOCK_NET_RESOURCE(NET_RESID);

   if (err != 0) 
   {
      so->so_error = err;
      return SOCKET_ERROR;
   }
   return 0;
}
Beispiel #13
0
int
t_socketclose(long s)
{
   struct socket *   so;
   int   err;

   so = LONG2SO(s);
   SOC_CHECK(so);
   so->so_error = 0;
   INET_TRACE ((INETM_CLOSE|INETM_SOCKET), ("INET:close, so %lx\n",so));

   LOCK_NET_RESOURCE(NET_RESID);
   err = soclose(so);
   UNLOCK_NET_RESOURCE(NET_RESID);

   if (err != 0) 
   {
      /* do not do the following assignment since the socket structure
         addressed by so has been freed by this point, jharan 12-10-98 */
      /*      so->so_error = err;   */
      return SOCKET_ERROR;
   }
   return 0;
}
Beispiel #14
0
/*
 * FUNCTION: bsd_ioctl()
 *
 * Perform a control operation on a socket
 *
 * PARAM1: s; IN - socket descriptor 
 * PARAM2: request; IN - requested control operation
 * PARAM3: arg; IN/OUT - arguments as required for control operation
 * RETURNS: 0 if successful, -1 if an error occurred.  The error is
 *          available via bsd_errno(s).
 */
int
bsd_ioctl(BSD_SOCKET s, 
          unsigned long request, ...)
{
   struct socket * so;
   va_list argptr;
   int iarg;

   so = LONG2SO(s);
   SOC_CHECK(so);

   va_start(argptr, request);

   switch (request)
   {
   case FIONBIO:
      iarg = va_arg(argptr, int);
      va_end(argptr);
      return t_setsockopt(s, SOL_SOCKET, SO_NONBLOCK, &iarg, sizeof(iarg));
   default:
      so->so_error = EINVAL;
      return -1;
   }
}
Beispiel #15
0
int
t_send(long s, 
   char *   buf,
   int      len, 
   int      flags)
{
   struct socket *   so;
   int   e;       /* error holder */
   int   total_sent  =  0;
   int   maxpkt;
   int   sendlen;
   int   sent;

   so = LONG2SO(s);
#ifdef SOC_CHECK_ALWAYS
   SOC_CHECK(so);
#endif
   if ((so->so_state & SO_IO_OK) != SS_ISCONNECTED)
   {
      so->so_error = EPIPE;
      return SOCKET_ERROR;
   }
   so->so_error = 0;

   /* If this is not a stream socket, assume it is bound and pass to
    * t_sendto() with a null sockaddr
    */
   if (so->so_type != SOCK_STREAM)
      return(t_sendto(s, buf, len, flags, NULL, 0));

   maxpkt = TCP_MSS;
   if(so->so_pcb)
   { 
      struct tcpcb * tp;
      tp = intotcpcb(so->so_pcb);   /* get tcp structure with mss */
      if(tp->t_maxseg)              /* Make sure it's set */
         maxpkt = tp->t_maxseg;
   }

   IN_PROFILER(PF_TCP, PF_ENTRY);       /* measure time in TCP */

   while (len)
   {
      if (len > maxpkt)
         sendlen = maxpkt;  /* take biggest block we can */
      else
         sendlen = len;
      sent = sendlen;

      LOCK_NET_RESOURCE(NET_RESID);
      e = sosend (so, NULL, buf, &sendlen, flags);
      UNLOCK_NET_RESOURCE(NET_RESID);
 
      if (e != 0)  /* sock_sendit failed? */
      {
         /* if we simply ran out of bufs, report back to caller. */
         if ((e == ENOBUFS) || (e == EWOULDBLOCK))
         {
            /* if we actually sent something before running out
             * of buffers, report what we sent; 
             * else, report the error and let the application 
             * retry the call later
             */
            if (total_sent != 0)
            {
               so->so_error = 0;
               break;      /* break out of while(len) loop */
            }
         }
         so->so_error = e;
         return SOCKET_ERROR;
      }
      /* if we can't send anymore, return now */
      if (sendlen != 0)
         break;         /* break out of while(len) loop */

      /* adjust numbers & pointers, and go do next send loop */
      sent -= sendlen;        /* subtract anything that didn't get sent */
      buf += sent;
      len -= sent;
      total_sent += sent;
   }

   IN_PROFILER(PF_TCP, PF_EXIT);        /* measure time in TCP */
   return total_sent;
}
Beispiel #16
0
int
t_sendto (long s, 
   char *   buf,
   int   len, 
   int   flags,
   struct sockaddr * to,
   int   tolen)
{
   struct socket *   so;
   int   sendlen;
   int   err;
   struct mbuf *     name;

   so = LONG2SO(s);
   SOC_CHECK(so);
   so->so_error = 0;

   switch (so->so_type)
   {
   case SOCK_STREAM:
      /* this is a stream socket, so pass this request through
       * t_send() for its large-send support.
       */
      return t_send(s, buf, len, flags);
      /*NOTREACHED*/
   case SOCK_DGRAM:
      /* datagram (UDP) socket -- prepare to check length */
      sendlen = udp_maxalloc();
      break;
#ifdef IP_RAW
   case SOCK_RAW:
      /* raw socket -- prepare to check length */
      sendlen = ip_raw_maxalloc(so->so_options & SO_HDRINCL);
      break;
#endif /* IP_RAW */
   default:
      /* socket has unknown type */
      dtrap();
      so->so_error = EFAULT;
      return SOCKET_ERROR;
      /*NOTREACHED*/
   }

   /* fall through for non-stream sockets: SOCK_DGRAM (UDP) and
    * SOCK_RAW (raw IP)
    */

   /* check length against underlying stack's maximum */
   if (len > sendlen)
   {
      so->so_error = EMSGSIZE;
      return SOCKET_ERROR;
   }

   /* if a sockaddr was passed, wrap it in an mbuf and pas it into the
    * bowels of the BSD code; else assume this is a bound UDP socket
    * and this call came from t_send() below.
    */

   if (to)  /* sockaddr was passed */
   {
      name = sockargs(to, tolen, MT_SONAME);
      if(name == NULL)
      {
         so->so_error = ENOMEM;
         return SOCKET_ERROR;
      }
   }
   else     /* hope user called bind() first... */
      name = NULL;
   
   sendlen = len;

   LOCK_NET_RESOURCE(NET_RESID);

   err = sosend (so, name, buf, &sendlen, flags);

   if (name)
      m_freem(name);

   UNLOCK_NET_RESOURCE(NET_RESID);

   if (err != 0)
   {
      so->so_error = err;
      return SOCKET_ERROR;
   }

   return (len - sendlen);
}
Beispiel #17
0
long
t_accept(long s, 
   struct sockaddr * addr,
   int * addrlen)
{
#ifdef SOCKDEBUG
   char logbuf[10];
#endif
   struct socket *   so;
   struct mbuf *  nam;

   so = LONG2SO(s);
   SOC_CHECK(so);
   DOMAIN_CHECK(so, *addrlen);

   so->so_error = 0;
   INET_TRACE (INETM_SOCKET,
      ("INET:accept:so %x so_qlen %d so_state %x\n", so, so->so_qlen, so->so_state));
   if ((so->so_options & SO_ACCEPTCONN) == 0)
   {
      so->so_error = EINVAL;
#ifdef SOCKDEBUG
      sprintf(logbuf, "t_accept[%d]: %d", __LINE__, so->so_error);
      glog_with_type(LOG_TYPE_DEBUG, logbuf, 1);
#endif
      return SOCKET_ERROR;
   }
   if ((so->so_state & SS_NBIO) && so->so_qlen == 0)
   {
      so->so_error = EWOULDBLOCK;
#ifdef SOCKDEBUG
      sprintf(logbuf, "t_accept[%d]: %d", __LINE__, so->so_error);
      glog_with_type(LOG_TYPE_DEBUG, logbuf, 1);
#endif
      return SOCKET_ERROR;
   }
   LOCK_NET_RESOURCE(NET_RESID);
   while (so->so_qlen == 0 && so->so_error == 0)
   {
      if (so->so_state & SS_CANTRCVMORE)
      {
         so->so_error = ECONNABORTED;
         UNLOCK_NET_RESOURCE(NET_RESID);
         return SOCKET_ERROR;
      }
      tcp_sleep ((char *)&so->so_timeo);
   }
   if (so->so_error)
   {
#ifdef SOCKDEBUG
      sprintf(logbuf, "t_accept[%d]: %d", __LINE__, so->so_error);
      glog_with_type(LOG_TYPE_DEBUG, logbuf, 1);
#endif
      UNLOCK_NET_RESOURCE(NET_RESID);
      return SOCKET_ERROR;
   }
   nam = m_getwithdata (MT_SONAME, sizeof (struct sockaddr));
   if (nam == NULL) 
   {
      UNLOCK_NET_RESOURCE(NET_RESID);
      so->so_error = ENOMEM;
#ifdef SOCKDEBUG
      sprintf(logbuf, "t_accept[%d]: %d", __LINE__, so->so_error);
      glog_with_type(LOG_TYPE_DEBUG, logbuf, 1);
#endif
      return SOCKET_ERROR;
   }
   { 
      struct socket *aso = so->so_q;
      if (soqremque (aso, 1) == 0)
         panic("accept");
      so = aso;
   }
   (void)soaccept (so, nam);
#ifdef TRACE_DEBUG
   { struct sockaddr_in *sin;
      sin = mtod(nam, struct sockaddr_in *);
      INET_TRACE (INETM_SOCKET, ("INET:accept:done so %lx port %d addr %lx\n",
       so, sin->sin_port, sin->sin_addr.s_addr));
   }
#endif   /* TRACE_INET */
   /* return the addressing info in the passed structure */
   if (addr != NULL)
      MEMCPY(addr, nam->m_data, *addrlen);
   m_freem (nam);
   UNLOCK_NET_RESOURCE(NET_RESID);
   SOC_RANGE(so);
   return SO2LONG(so);
}
Beispiel #18
0
int
t_setsockopt(long s,
   int   level,
   int   name,
   void * arg,
   int arglen)
{
   struct socket *   so;
   int   err;

   so = LONG2SO(s);
   SOC_CHECK(so);
   USE_ARG(arglen);

   LOCK_NET_RESOURCE (NET_RESID);

   so->so_error = 0;
   INET_TRACE (INETM_SOCKET,
    ("INET: setsockopt: name %x val %x valsize %d\n",
    name, val));

   /* is it a level IP_OPTIONS call? */
   if (level != IP_OPTIONS)
   {
      if ((err = sosetopt (so, name, arg)) != 0) 
      {
         so->so_error = err;
         UNLOCK_NET_RESOURCE (NET_RESID);
         return SOCKET_ERROR;
      }
   }
   else
   {
   /* level 1 options are for the IP packet level.
    * the info is carried in the socket CB, then put 
    * into the PACKET.
    */
      if (!so->so_optsPack)
      {
         so->so_optsPack = (struct ip_socopts *) SOCOPT_ALLOC (sizeof(struct ip_socopts *));
         if (!so->so_optsPack) 
         {
            so->so_error = ENOMEM;
            UNLOCK_NET_RESOURCE (NET_RESID);
            return SOCKET_ERROR;
         }
      }
      
      if (name == IP_TTL_OPT)
         so->so_optsPack->ip_ttl = (u_char)(*(int *)arg);
      else
      if (name == IP_TOS)
         so->so_optsPack->ip_tos = (u_char)(*(int *)arg);
	   else
	   if (name == IP_SCOPEID)
            so->so_optsPack->ip_scopeid = (u_char)(*(u_int *)arg);
      else
      {
         UNLOCK_NET_RESOURCE (NET_RESID);
         return SOCKET_ERROR;
      }   
   }

   UNLOCK_NET_RESOURCE (NET_RESID);
   return 0;
}
Beispiel #19
0
static int
t_getname(long s, struct sockaddr * addr, int * addrlen, int opcode)
{
   struct socket *   so;
   struct mbuf *  m;
   int   err;

   so = LONG2SO(s);
   SOC_CHECK(so);

   so->so_error = 0;
   INET_TRACE (INETM_SOCKET, ("INET:get[sock|peer]name so %x\n", so));
   if((opcode == PRU_PEERADDR) && (so->so_state & SS_ISCONNECTED) == 0)
   {
      so->so_error = ENOTCONN;
      return SOCKET_ERROR;
   }
   LOCK_NET_RESOURCE(NET_RESID);
   m = m_getwithdata (MT_SONAME, sizeof (struct sockaddr));
   if (m == NULL) 
   {
      so->so_error = ENOMEM;
      UNLOCK_NET_RESOURCE(NET_RESID);
      return SOCKET_ERROR;
   }
   so->so_req = opcode;
   if ((err = (*so->so_proto->pr_usrreq)(so, 0, m)) != 0)
      goto bad;

#ifdef IP_V4
   if(so->so_domain == AF_INET)
   {
      if(*addrlen < sizeof(struct sockaddr_in))
      {
         dtrap();    /* programming error */
         m_freem(m);
         UNLOCK_NET_RESOURCE(NET_RESID);
         return EINVAL;
      }
      MEMCPY(addr, m->m_data, sizeof(struct sockaddr_in));
      *addrlen = sizeof(struct sockaddr_in);
   }
#endif   /* IP_V4 */
#ifdef IP_V6
   if(so->so_domain == AF_INET6)
   {
      if(*addrlen < sizeof(struct sockaddr_in6))
      {
         dtrap();    /* programming error */
         m_freem(m);
         UNLOCK_NET_RESOURCE(NET_RESID);
         return EINVAL;
      }
      MEMCPY(addr, m->m_data, sizeof(struct sockaddr_in6));
      *addrlen = sizeof(struct sockaddr_in6);
   }
#endif   /* IP_V6 */


bad:
   m_freem(m);
   UNLOCK_NET_RESOURCE(NET_RESID);
   if (err) 
   {
      so->so_error = err;
      return SOCKET_ERROR;
   }
   return 0;
}
Beispiel #20
0
int
t_connect(long s, 
   struct sockaddr * addr,
   int   addrlen)
{
   struct socket *   so;
   struct mbuf *  nam;

   so = LONG2SO(s);
   SOC_CHECK(so);
   DOMAIN_CHECK(so, addrlen);

#ifdef NB_CONNECT
   /* need to test non blocking connect bits in case this is a 
      poll of a previous request */
   if (so->so_state & SS_NBIO)
   {
      if (so->so_state & SS_ISCONNECTING) /* still trying */
      {
         so->so_error = EINPROGRESS;
         return SOCKET_ERROR;
      }
      if (so->so_state & SS_ISCONNECTED)  /* connected OK */
      {
         so->so_error = 0;
         return 0;
      }
      if (so->so_state & SS_WASCONNECTING)
      {
         so->so_state &= ~SS_WASCONNECTING;
         if (so->so_error) /* connect error - maybe timeout */
            return SOCKET_ERROR;
      }
   }
#endif   /*  NB_CONNECT */

   so->so_error = 0;

   if ((nam = sockargs (addr, addrlen, MT_SONAME))
       == NULL)
   {
      so->so_error = ENOMEM;
      return SOCKET_ERROR;
   }

#ifdef TRACE_DEBUG
   { struct sockaddr_in *sin = (struct sockaddr_in *)uap->sap;
      INET_TRACE (INETM_SOCKET, ("INET: connect, port %d addr %lx\n",
       sin->sin_port, sin->sin_addr.s_addr));
   }
#endif   /* TRACE_DEBUG */

   LOCK_NET_RESOURCE(NET_RESID);
   if ((so->so_error = soconnect (so, nam)) != 0)
      goto bad;

#ifdef NB_CONNECT
   /* need to test non blocking connect bits after soconnect() call */
   if ((so->so_state & SS_NBIO)&& (so->so_state & SS_ISCONNECTING))
   {
      so->so_error = EINPROGRESS;
      goto bad;
   }
#endif   /*  NB_CONNECT */
   INET_TRACE (INETM_SOCKET, ("INET: connect, so %x so_state %x so_error %d\n",
    so, so->so_state, so->so_error));

   while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) 
   {
      tcp_sleep ((char *)&so->so_timeo);
   }
bad:
   if (so->so_error != EINPROGRESS)
      so->so_state &= ~(SS_ISCONNECTING|SS_WASCONNECTING);
   m_freem (nam);

   UNLOCK_NET_RESOURCE(NET_RESID);
   if (so->so_error)
   {
/*      printf("t_connect(): so_error = %d\n", so->so_error);*/
      return SOCKET_ERROR;

   }
      return 0;
}