1 /*
2  * Copyright (C) 2002-2003 Fhg Fokus
3  *
4  * This file is part of SEMS, a free SIP media server.
5  *
6  * SEMS is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version. This program is released under
10  * the GPL with the additional exemption that compiling, linking,
11  * and/or using OpenSSL is allowed.
12  *
13  * For a license to use the SEMS software under conditions
14  * other than those described here, or to purchase support for this
15  * software, please contact iptel.org by e-mail at the following addresses:
16  *    info@iptel.org
17  *
18  * SEMS is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  */
27 
28 #define __APPLE_USE_RFC_3542
29 #include <netinet/in.h>
30 
31 #include "AmRtpPacket.h"
32 #include "rtp/rtp.h"
33 #include "log.h"
34 #include "AmConfig.h"
35 
36 #include "sip/raw_sender.h"
37 #include "sip/ip_util.h"
38 
39 #include <assert.h>
40 #include <string.h>
41 #include <errno.h>
42 
43 #include <sys/socket.h>
44 #include <arpa/inet.h>
45 
46 #include "sip/msg_logger.h"
47 
48 #include "AmRtpMuxStream.h"
49 
50 AmRtpPacket::AmRtpPacket()
51   : data_offset(0)
52 {
53   // buffer will be overwritten by received packet
54   // of hdr+data - does not need to be set to 0s
55   //    memset(buffer,0,4096);
56 }
57 
58 AmRtpPacket::~AmRtpPacket()
59 {
60 }
61 
62 void AmRtpPacket::setAddr(struct sockaddr_storage* a)
63 {
64   memcpy(&addr,a,sizeof(sockaddr_storage));
65 }
66 
67 void AmRtpPacket::getAddr(struct sockaddr_storage* a)
68 {
69   memcpy(a,&addr,sizeof(sockaddr_storage));
70 }
71 
72 int AmRtpPacket::parse()
73 {
74   assert(buffer);
75   assert(b_size);
76 
77   rtp_hdr_t* hdr = (rtp_hdr_t*)buffer;
78   // ZRTP "Hello" packet has version == 0
79   if ((hdr->version != RTP_VERSION) && (hdr->version != 0))
80       {
81 	DBG("received RTP packet with unsupported version (%i).\n",
82 	    hdr->version);
83 	return -1;
84       }
85 
86   data_offset = sizeof(rtp_hdr_t) + (hdr->cc*4);
87 
88   if(hdr->x != 0) {
89     //#ifndef WITH_ZRTP
90     //if (AmConfig::IgnoreRTPXHdrs) {
91     //  skip the extension header
92     //#endif
93     if (b_size >= data_offset + 4) {
94       data_offset +=
95 	ntohs(((rtp_xhdr_t*) (buffer + data_offset))->len)*4;
96     }
97     // #ifndef WITH_ZRTP
98     //   } else {
99     //     DBG("RTP extension headers not supported.\n");
100     //     return -1;
101     //   }
102     // #endif
103   }
104 
105   payload = hdr->pt;
106   marker = hdr->m;
107   sequence = ntohs(hdr->seq);
108   timestamp = ntohl(hdr->ts);
109   ssrc = ntohl(hdr->ssrc);
110   version = hdr->version;
111 
112   if (data_offset > b_size) {
113     ERROR("bad rtp packet (hdr-size=%u;pkt-size=%u) !\n",
114 	  data_offset,b_size);
115     return -1;
116   }
117   d_size = b_size - data_offset;
118 
119   if(hdr->p){
120     if (buffer[b_size-1]>=d_size){
121       ERROR("bad rtp packet (invalid padding size) !\n");
122       return -1;
123     }
124     d_size -= buffer[b_size-1];
125   }
126 
127   return 0;
128 }
129 
130 unsigned char *AmRtpPacket::getData()
131 {
132   return &buffer[data_offset];
133 }
134 
135 unsigned char *AmRtpPacket::getBuffer()
136 {
137   return &buffer[0];
138 }
139 
140 int AmRtpPacket::compile(unsigned char* data_buf, unsigned int size)
141 {
142   assert(data_buf);
143   assert(size);
144 
145   d_size = size;
146   b_size = d_size + sizeof(rtp_hdr_t);
147   assert(b_size <= 4096);
148   rtp_hdr_t* hdr = (rtp_hdr_t*)buffer;
149 
150   if(b_size>sizeof(buffer)){
151     ERROR("builtin buffer size (%d) exceeded: %d\n",
152 	  (int)sizeof(buffer), b_size);
153     return -1;
154   }
155 
156   memset(hdr,0,sizeof(rtp_hdr_t));
157   hdr->version = RTP_VERSION;
158   hdr->m = marker;
159   hdr->pt = payload;
160 
161   hdr->seq = htons(sequence);
162   hdr->ts = htonl(timestamp);
163   hdr->ssrc = htonl(ssrc);
164 
165   data_offset = sizeof(rtp_hdr_t);
166   memcpy(&buffer[data_offset],data_buf,d_size);
167 
168   return 0;
169 }
170 
171 int AmRtpPacket::compile_raw(unsigned char* data_buf, unsigned int size)
172 {
173   if ((!size) || (!data_buf))
174     return -1;
175 
176   if(size>sizeof(buffer)){
177     ERROR("builtin buffer size (%d) exceeded: %d\n",
178 	  (int)sizeof(buffer), size);
179     return -1;
180   }
181 
182   memcpy(&buffer[0], data_buf, size);
183   b_size = size;
184 
185   return size;
186 }
187 
188 int AmRtpPacket::sendto(int sd)
189 {
190   int err = ::sendto(sd,buffer,b_size,0,
191 		     (const struct sockaddr *)&addr,
192 		     SA_len(&addr));
193 
194   if(err == -1){
195     ERROR("while sending RTP packet: %s\n",strerror(errno));
196     return -1;
197   }
198 
199   return 0;
200 }
201 
202 int AmRtpPacket::sendmsg(int sd, unsigned int sys_if_idx)
203 {
204   struct msghdr hdr;
205   struct cmsghdr* cmsg;
206 
207   union {
208 #ifndef __FreeBSD__
209     char cmsg4_buf[CMSG_SPACE(sizeof(struct in_pktinfo))];
210 #endif
211     char cmsg6_buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
212   } cmsg_buf;
213 
214   struct iovec msg_iov[1];
215   msg_iov[0].iov_base = (void*)buffer;
216   msg_iov[0].iov_len  = b_size;
217 
218   bzero(&hdr,sizeof(hdr));
219   hdr.msg_name = (void*)&addr;
220   hdr.msg_namelen = SA_len(&addr);
221   hdr.msg_iov = msg_iov;
222   hdr.msg_iovlen = 1;
223 
224   bzero(&cmsg_buf,sizeof(cmsg_buf));
225   hdr.msg_control = &cmsg_buf;
226   hdr.msg_controllen = sizeof(cmsg_buf);
227 
228   cmsg = CMSG_FIRSTHDR(&hdr);
229   if(addr.ss_family == AF_INET) {
230 #ifndef __FreeBSD__
231     cmsg->cmsg_level = IPPROTO_IP;
232     cmsg->cmsg_type = IP_PKTINFO;
233     cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
234 
235     struct in_pktinfo* pktinfo = (struct in_pktinfo*) CMSG_DATA(cmsg);
236     pktinfo->ipi_ifindex = sys_if_idx;
237 #endif
238   }
239   else if(addr.ss_family == AF_INET6) {
240     cmsg->cmsg_level = IPPROTO_IPV6;
241     cmsg->cmsg_type = IPV6_PKTINFO;
242     cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
243 
244     struct in6_pktinfo* pktinfo = (struct in6_pktinfo*) CMSG_DATA(cmsg);
245     pktinfo->ipi6_ifindex = sys_if_idx;
246   }
247 
248   hdr.msg_controllen = cmsg->cmsg_len;
249 
250   // bytes_sent = ;
251   if(::sendmsg(sd, &hdr, 0) < 0) {
252       ERROR("sendto: %s\n",strerror(errno));
253       return -1;
254   }
255 
256   return 0;
257 }
258 
259 int AmRtpPacket::send(int sd, unsigned int sys_if_idx,
260 		      sockaddr_storage* l_saddr, const std::string& rtp_mux_remote_ip, unsigned int rtp_mux_remote_port)
261 {
262   if (!rtp_mux_remote_ip.empty() && rtp_mux_remote_port)
263     return AmRtpMuxSender::instance()->send(buffer, b_size, rtp_mux_remote_ip, rtp_mux_remote_port, am_get_port(&addr));
264 
265   if(sys_if_idx && AmConfig::UseRawSockets) {
266     return raw_sender::send((char*)buffer,b_size,sys_if_idx,l_saddr,&addr);
267   }
268 
269   if(sys_if_idx && AmConfig::ForceOutboundIf) {
270     return sendmsg(sd,sys_if_idx);
271   }
272 
273   return sendto(sd);
274 }
275 
276 int AmRtpPacket::recv(int sd)
277 {
278   socklen_t recv_addr_len = sizeof(struct sockaddr_storage);
279   int ret = recvfrom(sd,buffer,sizeof(buffer),0,
280 		     (struct sockaddr*)&addr,
281 		     &recv_addr_len);
282 
283   if(ret > 0){
284 
285     if(ret > 4096)
286       return -1;
287 
288     b_size = ret;
289   }
290 
291   return ret;
292 }
293 
294 int AmRtpPacket::recv(unsigned char* pkt, size_t len)
295 {
296   b_size = len > sizeof(buffer) ? sizeof(buffer) : len;
297   memcpy(buffer, pkt, b_size);
298   return b_size;
299 }
300 
301 void AmRtpPacket::logReceived(msg_logger *logger, struct sockaddr_storage *laddr)
302 {
303   static const cstring empty;
304   logger->log((const char *)buffer, b_size, &addr, laddr, empty);
305 }
306 
307 void AmRtpPacket::logSent(msg_logger *logger, struct sockaddr_storage *laddr)
308 {
309   static const cstring empty;
310   logger->log((const char *)buffer, b_size, laddr, &addr, empty);
311 }
312 
313