Changeset View
Changeset View
Standalone View
Standalone View
sys/compat/freebsd32/freebsd32_misc.c
Show First 20 Lines • Show All 1,058 Lines • ▼ Show 20 Lines | #define FREEBSD32_ALIGN(p) \ | ||||
(((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES) | (((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES) | ||||
#define FREEBSD32_CMSG_SPACE(l) \ | #define FREEBSD32_CMSG_SPACE(l) \ | ||||
(FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l)) | (FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l)) | ||||
#define FREEBSD32_CMSG_DATA(cmsg) ((unsigned char *)(cmsg) + \ | #define FREEBSD32_CMSG_DATA(cmsg) ((unsigned char *)(cmsg) + \ | ||||
FREEBSD32_ALIGN(sizeof(struct cmsghdr))) | FREEBSD32_ALIGN(sizeof(struct cmsghdr))) | ||||
static size_t | static size_t | ||||
freebsd32_cmsg_convert(struct cmsghdr *cm, void *data, socklen_t datalen) | freebsd32_cmsg_convert(const struct cmsghdr *cm, void *data, socklen_t datalen) | ||||
{ | { | ||||
size_t copylen; | size_t copylen; | ||||
union { | union { | ||||
struct timespec32 ts; | struct timespec32 ts; | ||||
struct timeval32 tv; | struct timeval32 tv; | ||||
struct bintime32 bt; | struct bintime32 bt; | ||||
} tmp32; | } tmp32; | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | freebsd32_cmsg_convert(const struct cmsghdr *cm, void *data, socklen_t datalen) | ||||
return (copylen); | return (copylen); | ||||
} | } | ||||
static int | static int | ||||
freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control) | freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control) | ||||
{ | { | ||||
struct cmsghdr *cm; | struct cmsghdr *cm; | ||||
void *data; | void *data; | ||||
socklen_t clen, datalen, datalen_out; | socklen_t clen, datalen, datalen_out, oldclen; | ||||
int error; | int error; | ||||
caddr_t ctlbuf; | caddr_t ctlbuf; | ||||
int len, maxlen, copylen; | int len, maxlen, copylen; | ||||
struct mbuf *m; | struct mbuf *m; | ||||
error = 0; | error = 0; | ||||
len = msg->msg_controllen; | len = msg->msg_controllen; | ||||
maxlen = msg->msg_controllen; | maxlen = msg->msg_controllen; | ||||
msg->msg_controllen = 0; | msg->msg_controllen = 0; | ||||
m = control; | |||||
ctlbuf = msg->msg_control; | ctlbuf = msg->msg_control; | ||||
for (m = control; m != NULL && len > 0; m = m->m_next) { | |||||
while (m && len > 0) { | |||||
cm = mtod(m, struct cmsghdr *); | cm = mtod(m, struct cmsghdr *); | ||||
clen = m->m_len; | clen = m->m_len; | ||||
while (cm != NULL) { | while (cm != NULL) { | ||||
if (sizeof(struct cmsghdr) > clen || | if (sizeof(struct cmsghdr) > clen || | ||||
cm->cmsg_len > clen) { | cm->cmsg_len > clen) { | ||||
error = EINVAL; | error = EINVAL; | ||||
break; | break; | ||||
} | } | ||||
data = CMSG_DATA(cm); | data = CMSG_DATA(cm); | ||||
datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; | datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; | ||||
datalen_out = freebsd32_cmsg_convert(cm, data, datalen); | datalen_out = freebsd32_cmsg_convert(cm, data, datalen); | ||||
/* Adjust message length */ | /* | ||||
cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + | * Copy out the message header. Preserve the native | ||||
datalen_out; | * message size in case we need to inspect the message | ||||
* contents later. | |||||
/* Copy cmsghdr */ | */ | ||||
copylen = sizeof(struct cmsghdr); | copylen = sizeof(struct cmsghdr); | ||||
if (len < copylen) { | if (len < copylen) { | ||||
msg->msg_flags |= MSG_CTRUNC; | msg->msg_flags |= MSG_CTRUNC; | ||||
copylen = len; | m_dispose_extcontrolm(m); | ||||
goto exit; | |||||
} | } | ||||
oldclen = cm->cmsg_len; | |||||
cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + | |||||
datalen_out; | |||||
error = copyout(cm, ctlbuf, copylen); | error = copyout(cm, ctlbuf, copylen); | ||||
if (error) | cm->cmsg_len = oldclen; | ||||
if (error != 0) | |||||
goto exit; | goto exit; | ||||
ctlbuf += FREEBSD32_ALIGN(copylen); | ctlbuf += FREEBSD32_ALIGN(copylen); | ||||
len -= FREEBSD32_ALIGN(copylen); | len -= FREEBSD32_ALIGN(copylen); | ||||
if (len <= 0) | |||||
break; | |||||
/* Copy data */ | |||||
copylen = datalen_out; | copylen = datalen_out; | ||||
if (len < copylen) { | if (len < copylen) { | ||||
msg->msg_flags |= MSG_CTRUNC; | msg->msg_flags |= MSG_CTRUNC; | ||||
copylen = len; | m_dispose_extcontrolm(m); | ||||
break; | |||||
} | } | ||||
/* Copy out the message data. */ | |||||
error = copyout(data, ctlbuf, copylen); | error = copyout(data, ctlbuf, copylen); | ||||
if (error) | if (error) | ||||
goto exit; | goto exit; | ||||
ctlbuf += FREEBSD32_ALIGN(copylen); | ctlbuf += FREEBSD32_ALIGN(copylen); | ||||
len -= FREEBSD32_ALIGN(copylen); | len -= FREEBSD32_ALIGN(copylen); | ||||
if (CMSG_SPACE(datalen) < clen) { | if (CMSG_SPACE(datalen) < clen) { | ||||
clen -= CMSG_SPACE(datalen); | clen -= CMSG_SPACE(datalen); | ||||
cm = (struct cmsghdr *) | cm = (struct cmsghdr *) | ||||
((caddr_t)cm + CMSG_SPACE(datalen)); | ((caddr_t)cm + CMSG_SPACE(datalen)); | ||||
} else { | } else { | ||||
clen = 0; | clen = 0; | ||||
cm = NULL; | cm = NULL; | ||||
} | } | ||||
msg->msg_controllen += FREEBSD32_ALIGN(sizeof(*cm)) + | |||||
ed: Nit: extraneous parentheses. | |||||
datalen_out; | |||||
} | } | ||||
m = m->m_next; | |||||
} | } | ||||
if (len == 0 && m != NULL) { | |||||
msg->msg_flags |= MSG_CTRUNC; | |||||
m_dispose_extcontrolm(m); | |||||
} | |||||
msg->msg_controllen = (len <= 0) ? maxlen : ctlbuf - (caddr_t)msg->msg_control; | |||||
exit: | exit: | ||||
return (error); | return (error); | ||||
} | } | ||||
int | int | ||||
freebsd32_recvmsg(td, uap) | freebsd32_recvmsg(td, uap) | ||||
struct thread *td; | struct thread *td; | ||||
struct freebsd32_recvmsg_args /* { | struct freebsd32_recvmsg_args /* { | ||||
int s; | int s; | ||||
struct msghdr32 *msg; | struct msghdr32 *msg; | ||||
Show All 20 Lines | freebsd32_recvmsg(td, uap) | ||||
msg.msg_flags = uap->flags; | msg.msg_flags = uap->flags; | ||||
uiov = msg.msg_iov; | uiov = msg.msg_iov; | ||||
msg.msg_iov = iov; | msg.msg_iov = iov; | ||||
controlp = (msg.msg_control != NULL) ? &control : NULL; | controlp = (msg.msg_control != NULL) ? &control : NULL; | ||||
error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, controlp); | error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, controlp); | ||||
if (error == 0) { | if (error == 0) { | ||||
msg.msg_iov = uiov; | msg.msg_iov = uiov; | ||||
if (control != NULL) | if (control != NULL) | ||||
error = freebsd32_copy_msg_out(&msg, control); | error = freebsd32_copy_msg_out(&msg, control); | ||||
else | else | ||||
msg.msg_controllen = 0; | msg.msg_controllen = 0; | ||||
if (error == 0) | if (error == 0) | ||||
error = freebsd32_copyoutmsghdr(&msg, uap->msg); | error = freebsd32_copyoutmsghdr(&msg, uap->msg); | ||||
} | } | ||||
free(iov, M_IOV); | free(iov, M_IOV); | ||||
if (control != NULL) | if (control != NULL) { | ||||
if (error != 0) | |||||
m_dispose_extcontrolm(control); | |||||
m_freem(control); | m_freem(control); | ||||
} | |||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Copy-in the array of control messages constructed using alignment | * Copy-in the array of control messages constructed using alignment | ||||
* and padding suitable for a 32-bit environment and construct an | * and padding suitable for a 32-bit environment and construct an | ||||
* mbuf using alignment and padding suitable for a 64-bit kernel. | * mbuf using alignment and padding suitable for a 64-bit kernel. | ||||
▲ Show 20 Lines • Show All 2,241 Lines • Show Last 20 Lines |
Nit: extraneous parentheses.