1 /*
2 * Copyright (c) 2004-2006 Maxim Sobolev <sobomax@FreeBSD.org>
3 * Copyright (c) 2006-2019 Sippy Software, Inc., http://www.sippysoft.com
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 */
28
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <string.h>
32 #include <netinet/in.h>
33
34 #include "config_pp.h"
35
36 #include "rtpp_network.h"
37 #include "rtpp_network_io.h"
38
39 ssize_t
recvfromto(int s,void * buf,size_t len,struct sockaddr * from,socklen_t * fromlen,struct sockaddr * to,socklen_t * tolen,struct timeval * timeptr)40 recvfromto(int s, void *buf, size_t len, struct sockaddr *from,
41 socklen_t *fromlen, struct sockaddr *to, socklen_t *tolen,
42 struct timeval *timeptr)
43 {
44 /* We use a union to make sure hdr is aligned */
45 union {
46 struct cmsghdr hdr;
47 unsigned char buf[CMSG_SPACE(1024)];
48 } cmsgbuf;
49 #if !defined(__FreeBSD__)
50 struct in_pktinfo *pktinfo;
51 #endif
52 struct cmsghdr *cmsg;
53 struct msghdr msg;
54 struct iovec iov;
55 ssize_t rval;
56
57 memset(&msg, '\0', sizeof(msg));
58 iov.iov_base = buf;
59 iov.iov_len = len;
60 msg.msg_name = from;
61 msg.msg_namelen = *fromlen;
62 msg.msg_iov = &iov;
63 msg.msg_iovlen = 1;
64 msg.msg_control = cmsgbuf.buf;
65 msg.msg_controllen = sizeof(cmsgbuf.buf);
66
67 rval = recvmsg(s, &msg, 0);
68 if (rval < 0)
69 return (rval);
70
71 *tolen = 0;
72 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
73 cmsg = CMSG_NXTHDR(&msg, cmsg)) {
74 #if defined(__FreeBSD__)
75 if (cmsg->cmsg_level == IPPROTO_IP &&
76 cmsg->cmsg_type == IP_RECVDSTADDR) {
77 memcpy(&satosin(to)->sin_addr, CMSG_DATA(cmsg),
78 sizeof(struct in_addr));
79 to->sa_family = AF_INET;
80 *tolen = sizeof(struct sockaddr_in);
81 break;
82 }
83 #else
84 if (cmsg->cmsg_level == SOL_IP &&
85 cmsg->cmsg_type == IP_PKTINFO) {
86 pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg);
87 memcpy(&satosin(to)->sin_addr, &pktinfo->ipi_addr,
88 sizeof(struct in_addr));
89 to->sa_family = AF_INET;
90 *tolen = sizeof(struct sockaddr_in);
91 break;
92 }
93 #endif
94 if ((cmsg->cmsg_level == SOL_SOCKET)
95 && (cmsg->cmsg_type == SCM_TIMESTAMP)) {
96 memcpy(timeptr, CMSG_DATA(cmsg), sizeof(struct timeval));
97 }
98 }
99 *fromlen = msg.msg_namelen;
100 return (rval);
101 }
102