From b86ff5cc74b39af41f4db8bddd4919b2d7717a77 Mon Sep 17 00:00:00 2001
From: Walter Doekes <walter+github@wjd.nu>
Date: Wed, 12 Mar 2014 11:53:00 +0100
Subject: [PATCH 1/2] Add missing htons() and properly cast ports to unsigned.

---
 src/call.cpp      | 16 ++++++-------
 src/rtpstream.cpp | 34 ++++++++++++---------------
 src/sipp.cpp      | 12 +++++-----
 src/socket.cpp    | 58 ++++++++++++++++++++++++-----------------------
 4 files changed, 59 insertions(+), 61 deletions(-)

diff --git a/src/call.cpp b/src/call.cpp
index 11ecd5e0..ed577bec 100644
--- a/src/call.cpp
+++ b/src/call.cpp
@@ -254,7 +254,7 @@ void call::get_remote_media_addr(char *msg)
                 (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_flowinfo = 0;
                 (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_scope_id = 0;
                 (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_family = AF_INET6;
-                (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_port = audio_port;
+                (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_port = htons(audio_port);
                 (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_addr = ip_media;
             }
             video_port = get_remote_port_media(msg, PAT_VIDEO);
@@ -263,7 +263,7 @@ void call::get_remote_media_addr(char *msg)
                 (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_flowinfo = 0;
                 (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_scope_id = 0;
                 (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_family = AF_INET6;
-                (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_port = video_port;
+                (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_port = htons(video_port);
                 (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_addr = ip_media;
             }
             hasMediaInformation = 1;
@@ -276,14 +276,14 @@ void call::get_remote_media_addr(char *msg)
             if (audio_port) {
                 /* We have audio in the SDP: set the to_audio addr */
                 (_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_family = AF_INET;
-                (_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_port = audio_port;
+                (_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_port = htons(audio_port);
                 (_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_addr.s_addr = ip_media;
             }
             video_port = get_remote_port_media(msg, PAT_VIDEO);
             if (video_port) {
                 /* We have video in the SDP: set the to_video addr */
                 (_RCAST(struct sockaddr_in *, &(play_args_v.to)))->sin_family = AF_INET;
-                (_RCAST(struct sockaddr_in *, &(play_args_v.to)))->sin_port = video_port;
+                (_RCAST(struct sockaddr_in *, &(play_args_v.to)))->sin_port = htons(video_port);
                 (_RCAST(struct sockaddr_in *, &(play_args_v.to)))->sin_addr.s_addr = ip_media;
             }
             hasMediaInformation = 1;
@@ -2135,15 +2135,15 @@ char* call::createSendingMessage(SendingMessage *src, int P_index, char *msg_buf
             }
             if (strstr(begin, "audio")) {
                 if (media_ip_is_ipv6) {
-                    (_RCAST(struct sockaddr_in6 *, &(play_args_a.from)))->sin6_port = port;
+                    (_RCAST(struct sockaddr_in6 *, &(play_args_a.from)))->sin6_port = htons(port);
                 } else {
-                    (_RCAST(struct sockaddr_in *, &(play_args_a.from)))->sin_port = port;
+                    (_RCAST(struct sockaddr_in *, &(play_args_a.from)))->sin_port = htons(port);
                 }
             } else if (strstr(begin, "video")) {
                 if (media_ip_is_ipv6) {
-                    (_RCAST(struct sockaddr_in6 *, &(play_args_v.from)))->sin6_port = port;
+                    (_RCAST(struct sockaddr_in6 *, &(play_args_v.from)))->sin6_port = htons(port);
                 } else {
-                    (_RCAST(struct sockaddr_in *, &(play_args_v.from)))->sin_port = port;
+                    (_RCAST(struct sockaddr_in *, &(play_args_v.from)))->sin_port = htons(port);
                 }
             } else {
                 ERROR("media_port keyword with no audio or video on the current line (%s)", begin);
diff --git a/src/rtpstream.cpp b/src/rtpstream.cpp
index c4bc024c..35040285 100644
--- a/src/rtpstream.cpp
+++ b/src/rtpstream.cpp
@@ -727,11 +727,9 @@ int rtpstream_get_localport (int *rtpsocket, int *rtcpsocket)
     }
 
     if (media_ip_is_ipv6) {
-      (_RCAST(struct sockaddr_in6 *,&address))->sin6_port =
-        htons((short)port_number);
+      (_RCAST(struct sockaddr_in6 *,&address))->sin6_port = htons((unsigned short)port_number);
     } else {
-      (_RCAST(struct sockaddr_in *,&address))->sin_port=
-        htons((short)port_number);
+      (_RCAST(struct sockaddr_in *,&address))->sin_port = htons((unsigned short)port_number);
     }
     if (bind(*rtpsocket,(sockaddr *)(void *)&address,
          SOCK_ADDR_SIZE(&address)) == 0) {
@@ -758,11 +756,9 @@ int rtpstream_get_localport (int *rtpsocket, int *rtcpsocket)
   if (*rtcpsocket!=-1) {
     /* try to bind it to our preferred address */
     if (media_ip_is_ipv6) {
-      (_RCAST(struct sockaddr_in6 *,&address))->sin6_port =
-        htons((short)port_number+1);
+      (_RCAST(struct sockaddr_in6 *,&address))->sin6_port = htons((unsigned short)port_number + 1);
     } else {
-      (_RCAST(struct sockaddr_in *,&address))->sin_port=
-        htons((short)port_number+1);
+      (_RCAST(struct sockaddr_in *,&address))->sin_port = htons((unsigned short)port_number + 1);
     }
     if (bind(*rtcpsocket,(sockaddr *)(void *)&address,
          SOCK_ADDR_SIZE(&address))) {
@@ -925,45 +921,45 @@ void rtpstream_set_remote (rtpstream_callinfo_t *callinfo, int ip_ver, char *ip_
   /* Audio */
   if (audio_port) {
     if (media_ip_is_ipv6) {
-      (_RCAST(struct sockaddr_in6 *,&address))->sin6_port= htons((short)audio_port);
+      (_RCAST(struct sockaddr_in6 *,&address))->sin6_port = htons((unsigned short)audio_port);
     } else {
-      (_RCAST(struct sockaddr_in *,&address))->sin_port= htons((short)audio_port);
+      (_RCAST(struct sockaddr_in *,&address))->sin_port = htons((unsigned short)audio_port);
     }
     memcpy (&(taskinfo->remote_audio_rtp_addr),&address,sizeof(address));
 
     if (media_ip_is_ipv6) {
-      (_RCAST(struct sockaddr_in6 *,&address))->sin6_port= htons((short)audio_port+1);
+      (_RCAST(struct sockaddr_in6 *,&address))->sin6_port = htons((unsigned short)audio_port + 1);
     } else {
-      (_RCAST(struct sockaddr_in *,&address))->sin_port= htons((short)audio_port+1);
+      (_RCAST(struct sockaddr_in *,&address))->sin_port = htons((unsigned short)audio_port + 1);
     }
     memcpy (&(taskinfo->remote_audio_rtcp_addr),&address,sizeof(address));
 
-    taskinfo->flags&= ~TI_NULL_AUDIOIP;
+    taskinfo->flags &= ~TI_NULL_AUDIOIP;
   }
 
   /* Video */
   if (video_port) {
     if (media_ip_is_ipv6) {
-      (_RCAST(struct sockaddr_in6 *,&address))->sin6_port= htons((short)video_port);
+      (_RCAST(struct sockaddr_in6 *,&address))->sin6_port = htons((unsigned short)video_port);
     } else {
-      (_RCAST(struct sockaddr_in *,&address))->sin_port= htons((short)video_port);
+      (_RCAST(struct sockaddr_in *,&address))->sin_port = htons((unsigned short)video_port);
     }
     memcpy (&(taskinfo->remote_video_rtp_addr),&address,sizeof(address));
 
     if (media_ip_is_ipv6) {
-      (_RCAST(struct sockaddr_in6 *,&address))->sin6_port= htons((short)video_port+1);
+      (_RCAST(struct sockaddr_in6 *,&address))->sin6_port = htons((unsigned short)video_port + 1);
     } else {
-      (_RCAST(struct sockaddr_in *,&address))->sin_port= htons((short)video_port+1);
+      (_RCAST(struct sockaddr_in *,&address))->sin_port = htons((unsigned short)video_port + 1);
     }
     memcpy (&(taskinfo->remote_video_rtcp_addr),&address,sizeof(address));
 
-	taskinfo->flags&= ~TI_NULL_VIDEOIP;
+    taskinfo->flags &= ~TI_NULL_VIDEOIP;
   }
 
   /* ok, we are done with the shared memory objects. let go mutex */
   pthread_mutex_unlock (&(taskinfo->mutex));
 
-  taskinfo->flags|= TI_RECONNECTSOCKET;
+  taskinfo->flags |= TI_RECONNECTSOCKET;
 
   /* may want to start a playback (listen) task here if no task running? */
   /* only makes sense if we decide to send 0-filled packets on idle */
diff --git a/src/sipp.cpp b/src/sipp.cpp
index 4e1bad4f..58c6f5fb 100644
--- a/src/sipp.cpp
+++ b/src/sipp.cpp
@@ -1623,10 +1623,10 @@ int main(int argc, char *argv[])
 
                 if (remote_sending_sockaddr.ss_family == AF_INET) {
                     (_RCAST(struct sockaddr_in *, &remote_sending_sockaddr))->sin_port =
-                        htons((short)remote_s_p);
+                        htons((unsigned short)remote_s_p);
                 } else {
                     (_RCAST(struct sockaddr_in6 *, &remote_sending_sockaddr))->sin6_port =
-                        htons((short)remote_s_p);
+                        htons((unsigned short)remote_s_p);
                 }
                 use_remote_sending_addr = 1 ;
 
@@ -2034,10 +2034,10 @@ int main(int argc, char *argv[])
 
             if (media_sockaddr.ss_family == AF_INET) {
                 (_RCAST(struct sockaddr_in *,&media_sockaddr))->sin_port =
-                    htons((short)media_port);
+                    htons((unsigned short)media_port);
             } else {
                 (_RCAST(struct sockaddr_in6 *,&media_sockaddr))->sin6_port =
-                    htons((short)media_port);
+                    htons((unsigned short)media_port);
                 media_ip_is_ipv6 = true;
             }
             strcpy(media_ip_escaped, media_ip);
@@ -2064,11 +2064,11 @@ int main(int argc, char *argv[])
 
         if (media_sockaddr.ss_family == AF_INET) {
             (_RCAST(struct sockaddr_in *,&media_sockaddr))->sin_port =
-                htons((short)media_port+2);
+                htons((unsigned short)media_port + 2);
             strcpy(media_ip_escaped, media_ip);
         } else {
             (_RCAST(struct sockaddr_in6 *,&media_sockaddr))->sin6_port =
-                htons((short)media_port+2);
+                htons((unsigned short)media_port+2);
             media_ip_is_ipv6 = true;
             strcpy(media_ip_escaped, media_ip);
         }
diff --git a/src/socket.cpp b/src/socket.cpp
index e3e00173..e3e78e43 100644
--- a/src/socket.cpp
+++ b/src/socket.cpp
@@ -514,7 +514,7 @@ void setup_ctrl_socket()
     }
 
     while (try_counter) {
-        ((struct sockaddr_in *)&ctl_sa)->sin_port = htons(port);
+        ((struct sockaddr_in *)&ctl_sa)->sin_port = htons((unsigned short)port);
         if (!bind(sock,(struct sockaddr *)&ctl_sa,sizeof(struct sockaddr_in))) {
             /* Bind successful */
             break;
@@ -816,7 +816,7 @@ static int handleSCTPNotify(struct sipp_socket* socket,char* buffer)
     return -2;
 }
 
-void set_multihome_addr(struct sipp_socket* socket,int port)
+void set_multihome_addr(struct sipp_socket* socket, int port)
 {
     if (strlen(multihome_ip)>0) {
         struct addrinfo * multi_addr;
@@ -836,8 +836,10 @@ void set_multihome_addr(struct sipp_socket* socket,int port)
         freeaddrinfo(multi_addr);
 
         if (port>0) {
-            if (secondaryaddress.ss_family==AF_INET) ((struct sockaddr_in*)&secondaryaddress)->sin_port=htons(port);
-            else if (secondaryaddress.ss_family==AF_INET6) ((struct sockaddr_in6*)&secondaryaddress)->sin6_port=htons(port);
+            if (secondaryaddress.ss_family==AF_INET)
+		    ((struct sockaddr_in*)&secondaryaddress)->sin_port = htons((unsigned short)port);
+            else if (secondaryaddress.ss_family==AF_INET6)
+		    ((struct sockaddr_in6*)&secondaryaddress)->sin6_port = htons((unsigned short)port);
         }
 
         int ret = sctp_bindx(socket->ss_fd, (struct sockaddr *) &secondaryaddress,
@@ -1461,9 +1463,9 @@ int sipp_bind_socket(struct sipp_socket *socket, struct sockaddr_storage *saddr,
 #ifdef USE_SCTP
     if (transport==T_SCTP && multisocket==1 && *port==-1) {
         if (socket->ss_ipv6) {
-            (_RCAST(struct sockaddr_in6 *, saddr))->sin6_port=0;
+            (_RCAST(struct sockaddr_in6 *, saddr))->sin6_port = 0;
         } else {
-            (_RCAST(struct sockaddr_in *, saddr))->sin_port=0;
+            (_RCAST(struct sockaddr_in *, saddr))->sin_port = 0;
         }
     }
 #endif
@@ -1487,9 +1489,9 @@ int sipp_bind_socket(struct sipp_socket *socket, struct sockaddr_storage *saddr,
     }
 
     if (socket->ss_ipv6) {
-        *port = ntohs((short)((_RCAST(struct sockaddr_in6 *, saddr))->sin6_port));
+        *port = ntohs((_RCAST(struct sockaddr_in6 *, saddr))->sin6_port);
     } else {
-        *port = ntohs((short)((_RCAST(struct sockaddr_in *, saddr))->sin_port));
+        *port = ntohs((_RCAST(struct sockaddr_in *, saddr))->sin_port);
     }
 
 #ifdef USE_SCTP
@@ -2500,11 +2502,11 @@ int open_connections()
             strcpy(remote_ip, get_inet_address(&remote_sockaddr));
             if (remote_sockaddr.ss_family == AF_INET) {
                 (_RCAST(struct sockaddr_in *, &remote_sockaddr))->sin_port =
-                    htons((short)remote_port);
+                    htons((unsigned short)remote_port);
                 strcpy(remote_ip_escaped, remote_ip);
             } else {
                 (_RCAST(struct sockaddr_in6 *, &remote_sockaddr))->sin6_port =
-                    htons((short)remote_port);
+                    htons((unsigned short)remote_port);
                 sprintf(remote_ip_escaped, "[%s]", remote_ip);
             }
             fprintf(stderr,"Done.\n");
@@ -2614,11 +2616,11 @@ int open_connections()
                 freeaddrinfo(local_addr);
             }
             if (local_ip_is_ipv6) {
-                (_RCAST(struct sockaddr_in6 *, &local_sockaddr))->sin6_port
-                    = htons((short)l_port);
+                (_RCAST(struct sockaddr_in6 *, &local_sockaddr))->sin6_port =
+                    htons((unsigned short)l_port);
             } else {
-                (_RCAST(struct sockaddr_in *, &local_sockaddr))->sin_port
-                    = htons((short)l_port);
+                (_RCAST(struct sockaddr_in *, &local_sockaddr))->sin_port =
+                    htons((unsigned short)l_port);
             }
             if(sipp_bind_socket(main_socket, &local_sockaddr, &local_port) == 0) {
                 break;
@@ -2667,11 +2669,11 @@ int open_connections()
         }
 
         if (local_ip_is_ipv6) {
-            (_RCAST(struct sockaddr_in6 *, &local_sockaddr))->sin6_port
-                = htons((short)user_port);
+            (_RCAST(struct sockaddr_in6 *, &local_sockaddr))->sin6_port =
+                htons((unsigned short)user_port);
         } else {
-            (_RCAST(struct sockaddr_in *, &local_sockaddr))->sin_port
-                = htons((short)user_port);
+            (_RCAST(struct sockaddr_in *, &local_sockaddr))->sin_port =
+                htons((unsigned short)user_port);
         }
         if(sipp_bind_socket(main_socket, &local_sockaddr, &local_port)) {
             ERROR_NO("Unable to bind main socket");
@@ -2721,11 +2723,11 @@ int open_connections()
                 freeaddrinfo(local_addr);
 
                 if (is_ipv6) {
-                    (_RCAST(struct sockaddr_in6 *, &server_sockaddr))->sin6_port
-                        = htons((short)local_port);
+                    (_RCAST(struct sockaddr_in6 *, &server_sockaddr))->sin6_port =
+                        htons((unsigned short)local_port);
                 } else {
-                    (_RCAST(struct sockaddr_in *, &server_sockaddr))->sin_port
-                        = htons((short)local_port);
+                    (_RCAST(struct sockaddr_in *, &server_sockaddr))->sin_port =
+                        htons((unsigned short)local_port);
                 }
 
                 sipp_customize_socket(sock);
@@ -2837,10 +2839,10 @@ void connect_to_peer(char *peer_host, int peer_port, struct sockaddr_storage *pe
 
     if (peer_sockaddr->ss_family == AF_INET) {
         (_RCAST(struct sockaddr_in *,peer_sockaddr))->sin_port =
-            htons((short)peer_port);
+            htons((unsigned short)peer_port);
     } else {
         (_RCAST(struct sockaddr_in6 *,peer_sockaddr))->sin6_port =
-            htons((short)peer_port);
+            htons((unsigned short)peer_port);
         is_ipv6 = true;
     }
     strcpy(peer_ip, get_inet_address(peer_sockaddr));
@@ -2933,10 +2935,10 @@ void connect_local_twin_socket(char * twinSippHost)
 
     if (twinSipp_sockaddr.ss_family == AF_INET) {
         (_RCAST(struct sockaddr_in *,&twinSipp_sockaddr))->sin_port =
-            htons((short)twinSippPort);
+            htons((unsigned short)twinSippPort);
     } else {
         (_RCAST(struct sockaddr_in6 *,&twinSipp_sockaddr))->sin6_port =
-            htons((short)twinSippPort);
+            htons((unsigned short)twinSippPort);
         is_ipv6 = true;
     }
     strcpy(twinSippIp, get_inet_address(&twinSipp_sockaddr));
@@ -2949,11 +2951,11 @@ void connect_local_twin_socket(char * twinSippHost)
     if (!is_ipv6) {
         localTwin_sockaddr.ss_family = AF_INET;
         (_RCAST(struct sockaddr_in *,&localTwin_sockaddr))->sin_port =
-            htons((short)twinSippPort);
+            htons((unsigned short)twinSippPort);
     } else {
         localTwin_sockaddr.ss_family = AF_INET6;
         (_RCAST(struct sockaddr_in6 *,&localTwin_sockaddr))->sin6_port =
-            htons((short)twinSippPort);
+            htons((unsigned short)twinSippPort);
     }
 
     // add socket option to allow the use of it without the TCP timeout

From 08f292c479d2a2dfce957e5c3f4239e6dea55061 Mon Sep 17 00:00:00 2001
From: Walter Doekes <walter+github@wjd.nu>
Date: Wed, 12 Mar 2014 12:44:20 +0100
Subject: [PATCH 2/2] There's no need to be root to use pcapplay.

---
 include/send_packets.h |   1 +
 src/call.cpp           |  16 +++--
 src/prepare_pcap.c     |  48 ++++++++++---
 src/send_packets.c     | 149 ++++++++++++-----------------------------
 4 files changed, 93 insertions(+), 121 deletions(-)

diff --git a/include/send_packets.h b/include/send_packets.h
index 4c0dc86b..98eb2104 100644
--- a/include/send_packets.h
+++ b/include/send_packets.h
@@ -114,6 +114,7 @@ typedef struct {
     /* Used in send_packets thread */
     struct sockaddr_storage to;
     struct sockaddr_storage from;
+    int sock;
 } play_args_t;
 
 #ifdef __cplusplus
diff --git a/src/call.cpp b/src/call.cpp
index ed577bec..451d5089 100644
--- a/src/call.cpp
+++ b/src/call.cpp
@@ -244,11 +244,12 @@ uint16_t get_remote_port_media(const char *msg, int pattype)
  */
 void call::get_remote_media_addr(char *msg)
 {
-    uint16_t video_port, audio_port;
+    uint16_t audio_port = get_remote_port_media(msg, PAT_AUDIO);
+    uint16_t video_port = get_remote_port_media(msg, PAT_VIDEO);
+
     if (media_ip_is_ipv6) {
         struct in6_addr ip_media;
         if (get_remote_ipv6_media(msg, &ip_media)) {
-            audio_port = get_remote_port_media(msg, PAT_AUDIO);
             if (audio_port) {
                 /* We have audio in the SDP: set the to_audio addr */
                 (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_flowinfo = 0;
@@ -257,7 +258,6 @@ void call::get_remote_media_addr(char *msg)
                 (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_port = htons(audio_port);
                 (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_addr = ip_media;
             }
-            video_port = get_remote_port_media(msg, PAT_VIDEO);
             if (video_port) {
                 /* We have video in the SDP: set the to_video addr */
                 (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_flowinfo = 0;
@@ -272,14 +272,12 @@ void call::get_remote_media_addr(char *msg)
         uint32_t ip_media;
         ip_media = get_remote_ip_media(msg);
         if (ip_media != INADDR_NONE) {
-            audio_port = get_remote_port_media(msg, PAT_AUDIO);
             if (audio_port) {
                 /* We have audio in the SDP: set the to_audio addr */
                 (_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_family = AF_INET;
                 (_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_port = htons(audio_port);
                 (_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_addr.s_addr = ip_media;
             }
-            video_port = get_remote_port_media(msg, PAT_VIDEO);
             if (video_port) {
                 /* We have video in the SDP: set the to_video addr */
                 (_RCAST(struct sockaddr_in *, &(play_args_v.to)))->sin_family = AF_INET;
@@ -289,6 +287,13 @@ void call::get_remote_media_addr(char *msg)
             hasMediaInformation = 1;
         }
     }
+
+    if (audio_port) {
+	play_args_a.sock = media_socket;
+    }
+    if (video_port) {
+	play_args_v.sock = media_socket_video;
+    }
 }
 
 #endif
@@ -616,6 +621,7 @@ void call::init(scenario * call_scenario, struct sipp_socket *socket, struct soc
     memset(&(play_args_v.to), 0, sizeof(struct sockaddr_storage));
     memset(&(play_args_a.from), 0, sizeof(struct sockaddr_storage));
     memset(&(play_args_v.from), 0, sizeof(struct sockaddr_storage));
+    play_args_a.sock = play_args_v.sock = -1;
     hasMediaInformation = 0;
     media_thread = 0;
 #endif
diff --git a/src/prepare_pcap.c b/src/prepare_pcap.c
index 92754b6c..9068e3c4 100644
--- a/src/prepare_pcap.c
+++ b/src/prepare_pcap.c
@@ -37,11 +37,9 @@
  * made available by the platform, as we had no problems to get them on all supported platforms.
  */
 
-typedef struct _ether_hdr {
-    char ether_dst[6];
-    char ether_src[6];
+typedef struct _ether_type_hdr {
     u_int16_t ether_type; /* we only need the type, so we can determine, if the next header is IPv4 or IPv6 */
-} ether_hdr;
+} ether_type_hdr;
 
 typedef struct _ipv6_hdr {
     char dontcare[6];
@@ -95,7 +93,8 @@ int prepare_pkts(char *file, pcap_pkts *pkts)
     u_int16_t base = 0xffff;
     u_long pktlen;
     pcap_pkt *pkt_index;
-    ether_hdr *ethhdr;
+    size_t ether_type_offset;
+    ether_type_hdr *ethhdr;
     struct iphdr *iphdr;
     ipv6_hdr *ip6hdr;
     struct udphdr *udphdr;
@@ -106,6 +105,19 @@ int prepare_pkts(char *file, pcap_pkts *pkts)
     if (!pcap)
         ERROR("Can't open PCAP file '%s'", file);
 
+    switch (pcap_datalink(pcap)) {
+    case DLT_EN10MB:
+        /* srcmac[6], dstmac[6], ethertype[2] */
+        ether_type_offset = 12;
+        break;
+    case DLT_LINUX_SLL:
+        /* some_stuff[14], ethertype[2] */
+        ether_type_offset = 14;
+        break;
+    default:
+        ERROR("Unsupported link-type %d", pcap_datalink(pcap));
+    }
+
 #if HAVE_PCAP_NEXT_EX
     while (pcap_next_ex (pcap, &pkthdr, (const u_char **) &pktdata) == 1) {
 #else
@@ -118,10 +130,12 @@ int prepare_pkts(char *file, pcap_pkts *pkts)
         ERROR("Can't allocate memory for pcap pkthdr");
     while ((pktdata = (u_char *) pcap_next (pcap, pkthdr)) != NULL) {
 #endif
-        ethhdr = (ether_hdr *)pktdata;
+        if (pkthdr->len != pkthdr->caplen)
+            ERROR("You've got truncated packets. Re-do dump with -s0");
+        ethhdr = (ether_type_hdr *)(pktdata + ether_type_offset);
         if (ntohs(ethhdr->ether_type) != 0x0800 /* IPv4 */
                 && ntohs(ethhdr->ether_type) != 0x86dd) { /* IPv6 */
-            fprintf(stderr, "Ignoring non IP{4,6} packet!\n");
+            WARNING("Ignoring non IP{4,6} packet!");
             continue;
         }
         iphdr = (struct iphdr *)((char *)ethhdr + sizeof(*ethhdr));
@@ -130,14 +144,14 @@ int prepare_pkts(char *file, pcap_pkts *pkts)
             pktlen = (u_long) pkthdr->len - sizeof(*ethhdr) - sizeof(*ip6hdr);
             ip6hdr = (ipv6_hdr *)(void *) iphdr;
             if (ip6hdr->nxt_header != IPPROTO_UDP) {
-                fprintf(stderr, "prepare_pcap.c: Ignoring non UDP packet!\n");
+                WARNING("prepare_pcap.c: Ignoring non UDP packet!");
                 continue;
             }
             udphdr = (struct udphdr *)((char *)ip6hdr + sizeof(*ip6hdr));
         } else {
             //ipv4
             if (iphdr->protocol != IPPROTO_UDP) {
-                fprintf(stderr, "prepare_pcap.c: Ignoring non UDP packet!\n");
+                WARNING("prepare_pcap.c: Ignoring non UDP packet!");
                 continue;
             }
 #if defined(__DARWIN) || defined(__CYGWIN) || defined(__FreeBSD__)
@@ -193,9 +207,23 @@ int prepare_pkts(char *file, pcap_pkts *pkts)
     pkts->max = pkts->pkts + n_pkts;
     pkts->max_length = max_length;
     pkts->base = base;
-    fprintf(stderr, "In pcap %s, npkts %d\nmax pkt length %ld\nbase port %d\n", file, n_pkts, max_length, base);
+    //fprintf(stderr, "In pcap %s, npkts %d\nmax pkt length %ld\nbase port %d\n", file, n_pkts, max_length, base);
     pcap_close(pcap);
 
     return 0;
 }
 
+/* TODO: right now we leak pkts when shutting down.
+ * But, we can't clean this up after send_packets, because it may get reused.
+ * Furthermore, there is a nasty memcpy that copies the pcap_pkts buffer for
+ * further use. That means that (a) this memory should stay alive until the
+ * end of the app and (b) it should not be freed multiple times. */
+void free_pkts(pcap_pkts *pkts)
+{
+    pcap_pkt *pkt_index = pkts->pkts;
+    while (pkt_index < pkts->max) {
+        free(pkt_index->data);
+        pkt_index++;
+    }
+    free(pkts->pkts);
+}
diff --git a/src/send_packets.c b/src/send_packets.c
index 5264df7e..9cbceb7a 100644
--- a/src/send_packets.c
+++ b/src/send_packets.c
@@ -44,6 +44,7 @@
 #include <pcap.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <arpa/inet.h>
 #include <netinet/udp.h>
 #if defined(__DARWIN) || defined(__CYGWIN) || defined(__FreeBSD__)
 #include <netinet/in.h>
@@ -54,7 +55,6 @@
 #include <errno.h>
 #include <string.h>
 #include <fcntl.h>
-#include <pthread.h>
 
 #include "send_packets.h"
 #include "prepare_pcap.h"
@@ -94,10 +94,9 @@ float2timer (float time, struct timeval *tvp)
 }
 
 /* buffer should be "file_name" */
-int
-parse_play_args (char *buffer, pcap_pkts *pkts)
+int parse_play_args(char *buffer, pcap_pkts *pkts)
 {
-    pkts->file = strdup (buffer);
+    pkts->file = strdup(buffer);
     prepare_pkts(pkts->file, pkts);
     return 1;
 }
@@ -111,22 +110,13 @@ void hexdump(char *p, int s)
     fprintf(stderr, "\n");
 }
 
-/*Safe threaded version*/
+/* Safe threaded version */
 void do_sleep (struct timeval *, struct timeval *,
                struct timeval *, struct timeval *);
-void send_packets_cleanup(void *arg)
-{
-    int * sock = (int *) arg;
-
-    // Close send socket
-    close(*sock);
-}
 
 int send_packets (play_args_t * play_args)
 {
-    int ret, sock, port_diff;
     pcap_pkt *pkt_index, *pkt_max;
-    uint16_t *from_port, *to_port;
     struct timeval didsleep = { 0, 0 };
     struct timeval start = { 0, 0 };
     struct timeval last = { 0, 0 };
@@ -135,122 +125,69 @@ int send_packets (play_args_t * play_args)
     struct sockaddr_storage *to = &(play_args->to);
     struct sockaddr_storage *from = &(play_args->from);
     struct udphdr *udp;
-    struct sockaddr_in6 to6, from6;
     char buffer[PCAP_MAXPACKET];
-    int temp_sum;
-    int len;
-
 #ifndef MSG_DONTWAIT
     int fd_flags;
 #endif
 
-    if (media_ip_is_ipv6) {
-        sock = socket(PF_INET6, SOCK_RAW, IPPROTO_UDP);
-        if (sock < 0) {
-            ERROR("Can't create raw IPv6 socket (need to run as root?): %s", strerror(errno));
-        }
-        from_port = &(((struct sockaddr_in6 *)(void *) from )->sin6_port);
-        len = sizeof(struct sockaddr_in6);
-        to_port = &(((struct sockaddr_in6 *)(void *) to )->sin6_port);
-    } else {
-        sock = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);
-        from_port = &(((struct sockaddr_in *)(void *) from )->sin_port);
-        len = sizeof(struct sockaddr_in);
-        to_port = &(((struct sockaddr_in *)(void *) to )->sin_port);
-        if (sock < 0) {
-            ERROR("Can't create raw IPv4 socket (need to run as root?): %s", strerror(errno));
-            return ret;
-        }
-    }
-
-
-    if ((ret = bind(sock, (struct sockaddr *)(void *)from, len))) {
-        ERROR("Can't bind media raw socket");
-        return ret;
-    }
-
 #ifndef MSG_DONTWAIT
-    fd_flags = fcntl(sock, F_GETFL , NULL);
+    fd_flags = fcntl(play_args->sock, F_GETFL, NULL);
     fd_flags |= O_NONBLOCK;
-    fcntl(sock, F_SETFL , fd_flags);
+    fcntl(sock, F_SETFL, fd_flags);
+# define SENDTO_FLAGS 0
+#else
+# define SENDTO_FLAGS MSG_DONTWAIT
 #endif
     udp = (struct udphdr *)buffer;
 
     pkt_index = pkts->pkts;
     pkt_max = pkts->max;
-
-    if (media_ip_is_ipv6) {
-        memset(&to6, 0, sizeof(to6));
-        memset(&from6, 0, sizeof(from6));
-        to6.sin6_family = AF_INET6;
-        from6.sin6_family = AF_INET6;
-        memcpy(&(to6.sin6_addr.s6_addr), &(((struct sockaddr_in6 *)(void *) to)->sin6_addr.s6_addr), sizeof(to6.sin6_addr.s6_addr));
-        memcpy(&(from6.sin6_addr.s6_addr), &(((struct sockaddr_in6 *)(void *) from)->sin6_addr.s6_addr), sizeof(from6.sin6_addr.s6_addr));
-    }
-
-
-    /* Ensure the sender socket is closed when the thread exits - this
-     * allows the thread to be cancelled cleanly.
-     */
-    pthread_cleanup_push(send_packets_cleanup, ((void *) &sock));
-
-
+    
     while (pkt_index < pkt_max) {
-        memcpy(udp, pkt_index->data, pkt_index->pktlen);
-        port_diff = ntohs (udp->uh_dport) - pkts->base;
-        // modify UDP ports
-        udp->uh_sport = htons(port_diff + *from_port);
-        udp->uh_dport = htons(port_diff + *to_port);
-
-        if (!media_ip_is_ipv6) {
-            temp_sum = checksum_carry(pkt_index->partial_check + check((u_int16_t *) &(((struct sockaddr_in *)(void *) from)->sin_addr.s_addr), 4) + check((u_int16_t *) &(((struct sockaddr_in *)(void *) to)->sin_addr.s_addr), 4) + check((u_int16_t *) &udp->uh_sport, 4));
-        } else {
-            temp_sum = checksum_carry(pkt_index->partial_check + check((u_int16_t *) &(from6.sin6_addr.s6_addr), 16) + check((u_int16_t *) &(to6.sin6_addr.s6_addr), 16) + check((u_int16_t *) &udp->uh_sport, 4));
-        }
+        int ret;
+        size_t buflen = pkt_index->pktlen - sizeof(*udp);
+        socklen_t socklen = (media_ip_is_ipv6 ? sizeof(struct sockaddr_in6)
+                             : sizeof(struct sockaddr_in));
 
-#ifndef _HPUX_LI
-#ifdef __HPUX
-        udp->uh_sum = (temp_sum>>16)+((temp_sum & 0xffff)<<16);
-#else
-        udp->uh_sum = temp_sum;
-#endif
-#else
-        udp->uh_sum = temp_sum;
-#endif
+        /* Fetch only the udp data, not the header */
+        memcpy(buffer, pkt_index->data + sizeof(*udp), buflen);
 
-        do_sleep ((struct timeval *) &pkt_index->ts, &last, &didsleep,
-                  &start);
-#ifdef MSG_DONTWAIT
-        if (!media_ip_is_ipv6) {
-            ret = sendto(sock, buffer, pkt_index->pktlen, MSG_DONTWAIT,
-                         (struct sockaddr *)(void *) to, sizeof(struct sockaddr_in));
-        } else {
-            ret = sendto(sock, buffer, pkt_index->pktlen, MSG_DONTWAIT,
-                         (struct sockaddr *)(void *) &to6, sizeof(struct sockaddr_in6));
-        }
-#else
-        if (!media_ip_is_ipv6) {
-            ret = sendto(sock, buffer, pkt_index->pktlen, 0,
-                         (struct sockaddr *)(void *) to, sizeof(struct sockaddr_in));
-        } else {
-            ret = sendto(sock, buffer, pkt_index->pktlen, 0,
-                         (struct sockaddr *)(void *) &to6, sizeof(struct sockaddr_in6));
-        }
-#endif
+        do_sleep((struct timeval *) &pkt_index->ts, &last, &didsleep, &start);
+
+        ret = sendto(play_args->sock, buffer, buflen, SENDTO_FLAGS, (struct sockaddr *) to, socklen);
         if (ret < 0) {
-            close(sock);
+            char from_addr[INET6_ADDRSTRLEN], to_addr[INET6_ADDRSTRLEN];
+            uint64_t from_port, to_port;
+
+            if (media_ip_is_ipv6) {
+                inet_ntop(AF_INET6, &((struct sockaddr_in6*)from)->sin6_addr.s6_addr,
+                          from_addr, INET6_ADDRSTRLEN);
+                from_port = ((struct sockaddr_in6 *)(void *)from)->sin6_port;
+                inet_ntop(AF_INET6, &((struct sockaddr_in6*)to)->sin6_addr.s6_addr,
+                          to_addr, INET6_ADDRSTRLEN);
+                to_port = ((struct sockaddr_in6 *)(void *)to)->sin6_port;
+            } else {
+                inet_ntop(AF_INET, &((struct sockaddr_in*)from)->sin_addr.s_addr,
+                          from_addr, INET6_ADDRSTRLEN);
+                from_port = ((struct sockaddr_in *)(void *)from)->sin_port;
+                inet_ntop(AF_INET, &((struct sockaddr_in*)to)->sin_addr.s_addr,
+                          to_addr, INET6_ADDRSTRLEN);
+                to_port = ((struct sockaddr_in *)(void *)to)->sin_port;
+            }
+
+            /* You need the -i setting? */
             WARNING("send_packets.c: sendto failed with error: %s", strerror(errno));
-            return( -1);
+            WARNING("UDP fail when sending from %s:%hu to %s:%hu", from_addr, ntohs(from_port),
+                    to_addr, ntohs(to_port));
+	    return -1;
         }
 
         rtp_pckts_pcap++;
         rtp_bytes_pcap += pkt_index->pktlen - sizeof(*udp);
-        memcpy (&last, &(pkt_index->ts), sizeof (struct timeval));
+        memcpy(&last, &(pkt_index->ts), sizeof(struct timeval));
         pkt_index++;
     }
 
-    /* Closing the socket is handled by pthread_cleanup_push()/pthread_cleanup_pop() */
-    pthread_cleanup_pop(1);
     return 0;
 }