forked from unpbook/unpv13e
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrecvfromflags.c
96 lines (80 loc) · 2.32 KB
/
recvfromflags.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/* include recvfrom_flags1 */
#include "unp.h"
#include <sys/param.h> /* ALIGN macro for CMSG_NXTHDR() macro */
ssize_t
recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp,
SA *sa, socklen_t *salenptr, struct unp_in_pktinfo *pktp)
{
struct msghdr msg;
struct iovec iov[1];
ssize_t n;
#ifdef HAVE_MSGHDR_MSG_CONTROL
struct cmsghdr *cmptr;
union {
struct cmsghdr cm;
char control[CMSG_SPACE(sizeof(struct in_addr)) +
CMSG_SPACE(sizeof(struct unp_in_pktinfo))];
} control_un;
msg.msg_control = control_un.control;
msg.msg_controllen = sizeof(control_un.control);
msg.msg_flags = 0;
#else
bzero(&msg, sizeof(msg)); /* make certain msg_accrightslen = 0 */
#endif
msg.msg_name = sa;
msg.msg_namelen = *salenptr;
iov[0].iov_base = ptr;
iov[0].iov_len = nbytes;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
if ( (n = recvmsg(fd, &msg, *flagsp)) < 0)
return(n);
*salenptr = msg.msg_namelen; /* pass back results */
if (pktp)
bzero(pktp, sizeof(struct unp_in_pktinfo)); /* 0.0.0.0, i/f = 0 */
/* end recvfrom_flags1 */
/* include recvfrom_flags2 */
#ifndef HAVE_MSGHDR_MSG_CONTROL
*flagsp = 0; /* pass back results */
return(n);
#else
*flagsp = msg.msg_flags; /* pass back results */
if (msg.msg_controllen < sizeof(struct cmsghdr) ||
(msg.msg_flags & MSG_CTRUNC) || pktp == NULL)
return(n);
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr != NULL;
cmptr = CMSG_NXTHDR(&msg, cmptr)) {
#ifdef IP_RECVDSTADDR
if (cmptr->cmsg_level == IPPROTO_IP &&
cmptr->cmsg_type == IP_RECVDSTADDR) {
memcpy(&pktp->ipi_addr, CMSG_DATA(cmptr),
sizeof(struct in_addr));
continue;
}
#endif
#ifdef IP_RECVIF
if (cmptr->cmsg_level == IPPROTO_IP &&
cmptr->cmsg_type == IP_RECVIF) {
struct sockaddr_dl *sdl;
sdl = (struct sockaddr_dl *) CMSG_DATA(cmptr);
pktp->ipi_ifindex = sdl->sdl_index;
continue;
}
#endif
err_quit("unknown ancillary data, len = %d, level = %d, type = %d",
cmptr->cmsg_len, cmptr->cmsg_level, cmptr->cmsg_type);
}
return(n);
#endif /* HAVE_MSGHDR_MSG_CONTROL */
}
/* end recvfrom_flags2 */
ssize_t
Recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp,
SA *sa, socklen_t *salenptr, struct unp_in_pktinfo *pktp)
{
ssize_t n;
n = recvfrom_flags(fd, ptr, nbytes, flagsp, sa, salenptr, pktp);
if (n < 0)
err_quit("recvfrom_flags error");
return(n);
}