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