📄 bsdsock.c
字号:
/* FILENAME: bsdsock.c
*
* Copyright 2000 InterNiche Technologies Inc. All rights reserved.
*
* BSD sockets porting aid
*
* MODULE: misclib
* ROUTINES: bsd_accept(), bsd_getpeername(), bsd_getsockname(),
* bsd_getsockopt(), bsd_inet_aton(), bsd_inet_ntoa(),
* bsd_recvfrom(), bsd_select(), bsd_setsockopt(),
* bsd_i_sockoptlen()
* PORTABLE: yes
*/
#include "ipport.h"
#ifdef BSD_SOCKETS
#include <stdarg.h>
#include "netbuf.h"
#include "net.h"
#ifdef IP_MULTICAST
#include "ip.h"
#endif
#include "bsdsock.h"
#include "sockvar.h"
/* 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;
int laddrlen = 0;
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 == NULL)
{
so->so_error = EFAULT;
return -1;
}
laddrlen = *addrlen;
}
lret = t_accept(s, &laddr);
/* 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 (laddrlen > sizeof(struct sockaddr_in))
laddrlen = sizeof(struct sockaddr_in);
MEMCPY(addr, &laddr, laddrlen);
*addrlen = laddrlen;
}
return lret;
}
/* 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);
/* 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.
*/
if (lret != -1)
{
if (lnamelen > sizeof(struct sockaddr_in))
lnamelen = sizeof(struct sockaddr_in);
MEMCPY(name, &lname, lnamelen);
*namelen = lnamelen;
}
return lret;
}
/* FUNCTION: bsd_getsockname()
*
* Gets the name of the socket.
*
* 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_getsockname(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_getsockname(s, &lname);
/* 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.
*/
if (lret != -1)
{
if (lnamelen > sizeof(struct sockaddr_in))
lnamelen = sizeof(struct sockaddr_in);
MEMCPY(name, &lname, lnamelen);
*namelen = lnamelen;
}
return lret;
}
/* FUNCTION: bsd_i_sockoptlen()
*
* Get the minimum length of a named socket option
*
* PARAM1: level; IN - the level of the option
* PARAM2: name; IN - the name of the option
* RETURNS: minimum length of the named socket option, in bytes
*/
int
bsd_i_sockoptlen(int level,
int name)
{
USE_ARG(level);
switch (name)
{
case SO_BIO:
case SO_NBIO:
/* these don't use an option value */
return 0;
case SO_LINGER:
/* this option is a struct linger */
return sizeof(struct linger);
case SO_RCVTIMEO:
case SO_SNDTIMEO:
/* these options are type short */
return sizeof(short);
case SO_KEEPALIVE:
case SO_DONTROUTE:
case SO_BROADCAST:
case SO_REUSEADDR:
case SO_OOBINLINE:
case SO_SNDBUF:
case SO_RCVBUF:
case SO_NONBLOCK:
case SO_ERROR:
case SO_TYPE:
/* these options are type int */
return sizeof(int);
#ifdef TCP_ZEROCOPY
case SO_CALLBACK:
/* this option is a pointer to a function returning int */
return sizeof(int (*)());
#endif /* TCP_ZEROCOPY */
#ifdef IP_MULTICAST
case IP_MULTICAST_IF:
/* this option is type ip_addr */
return sizeof(ip_addr);
case IP_MULTICAST_TTL:
case IP_MULTICAST_LOOP:
/* these options are type u_char */
return sizeof(u_char);
case IP_ADD_MEMBERSHIP:
case IP_DROP_MEMBERSHIP:
/* these options are struct ip_mreq */
return sizeof(struct ip_mreq);
#endif /* IP_MULTICAST */
default:
/* we don't know what type these options are */
return 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, name, opt);
/* if it worked, copy the option length back for the caller's use */
if (e == 0)
{
*optlen = loptlen;
}
return e;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -