File 0002-rfc2466.patch of Package pjproject
pjnath/src/pjnath/ice_session.c | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 176 insertions(+)
Index: pjproject-2.10/pjnath/src/pjnath/ice_session.c
===================================================================
--- pjproject-2.10.orig/pjnath/src/pjnath/ice_session.c
+++ pjproject-2.10/pjnath/src/pjnath/ice_session.c
@@ -30,6 +30,21 @@
#include <pj/rand.h>
#include <pj/string.h>
+#if defined(_WIN32) || defined(__APPLE__)
+/* TODO(sblin): find an alternative for these paltforms */
+#else
+/* The following headers are used to get DEPRECATED addresses
+ * as specified in RFC 2462 Section 5.5.4
+ * https://tools.ietf.org/html/rfc2462#section-5.5.4
+ */
+#include <arpa/inet.h>
+#include <asm/types.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#endif
+
/* String names for candidate types */
static const char *cand_type_names[] =
{
@@ -713,6 +728,144 @@ static pj_uint32_t CALC_CAND_PRIO(pj_ice
#endif
}
+/* retrieve invalid addresses and store it in a string */
+static PJ_DEF(void) get_invalid_addresses(char** addresses, size_t* size)
+{
+#if defined(_WIN32) || defined(__APPLE__)
+ // PJ_TODO("sblin: find alternative for WIN32 and APPLE");
+#else
+ struct {
+ struct nlmsghdr nlmsg_info;
+ struct ifaddrmsg ifaddrmsg_info;
+ } netlink_req;
+
+ int fd;
+
+ long pagesize = sysconf(_SC_PAGESIZE);
+
+ if (!pagesize)
+ pagesize = 4096; /* Assume pagesize is 4096 if sysconf() failed */
+
+ fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if(fd < 0) {
+ perror("socket initialization error: abort");
+ return;
+ }
+
+ int rtn;
+
+ bzero(&netlink_req, sizeof(netlink_req));
+
+ netlink_req.nlmsg_info.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
+ netlink_req.nlmsg_info.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
+ netlink_req.nlmsg_info.nlmsg_type = RTM_GETADDR;
+ netlink_req.nlmsg_info.nlmsg_pid = getpid();
+
+ netlink_req.ifaddrmsg_info.ifa_family = AF_INET6;
+
+ rtn = send(fd, &netlink_req, netlink_req.nlmsg_info.nlmsg_len, 0);
+ if(rtn < 0) {
+ perror("send error: abort");
+ return;
+ }
+
+ char read_buffer[pagesize];
+ struct nlmsghdr *nlmsg_ptr;
+ int nlmsg_len;
+
+ size_t idx = 0;
+ /* Will store all deprecated addresses into a string */
+ char* deprecatedAddrs = malloc(256*sizeof(char)*PJ_INET6_ADDRSTRLEN);
+ if (!deprecatedAddrs) {
+ perror("malloc error: abort");
+ return;
+ }
+
+ while(1) {
+ int rtn;
+
+ bzero(read_buffer, pagesize);
+ rtn = recv(fd, read_buffer, pagesize, 0);
+ if(rtn < 0) {
+ perror ("recv(): ");
+ free(deprecatedAddrs);
+ return;
+ }
+
+ nlmsg_ptr = (struct nlmsghdr *) read_buffer;
+ nlmsg_len = rtn;
+
+ if (nlmsg_len < sizeof (struct nlmsghdr)) {
+ perror ("Received an incomplete netlink packet");
+ free(deprecatedAddrs);
+ return;
+ }
+
+ if (nlmsg_ptr->nlmsg_type == NLMSG_DONE)
+ break;
+
+ for(; NLMSG_OK(nlmsg_ptr, nlmsg_len);
+ nlmsg_ptr = NLMSG_NEXT(nlmsg_ptr, nlmsg_len))
+ {
+ struct ifaddrmsg *ifaddrmsg_ptr;
+ struct rtattr *rtattr_ptr;
+ int ifaddrmsg_len;
+
+ ifaddrmsg_ptr = (struct ifaddrmsg *) NLMSG_DATA(nlmsg_ptr);
+
+ if (ifaddrmsg_ptr->ifa_flags & IFA_F_DEPRECATED ||
+ ifaddrmsg_ptr->ifa_flags & IFA_F_TENTATIVE)
+ {
+ rtattr_ptr = (struct rtattr *) IFA_RTA(ifaddrmsg_ptr);
+ ifaddrmsg_len = IFA_PAYLOAD(nlmsg_ptr);
+
+ for(;RTA_OK(rtattr_ptr, ifaddrmsg_len);
+ rtattr_ptr = RTA_NEXT(rtattr_ptr, ifaddrmsg_len))
+ {
+ switch(rtattr_ptr->rta_type) {
+ case IFA_ADDRESS:
+ /* Any 256 obsolete ips (should not happen), resize the array. */
+ if (idx > 0 && idx % 256 == 0) {
+ char* newDeprecated = realloc(deprecatedAddrs,
+ (idx + 256)*sizeof(char)*PJ_INET6_ADDRSTRLEN);
+ if (newDeprecated == NULL) {
+ perror("realloc error: abort");
+ free(deprecatedAddrs);
+ return;
+ }
+ deprecatedAddrs = newDeprecated;
+ }
+ /* Store deprecated IP */
+ inet_ntop(ifaddrmsg_ptr->ifa_family,
+ RTA_DATA(rtattr_ptr),
+ &deprecatedAddrs[idx*PJ_INET6_ADDRSTRLEN],
+ sizeof(char)*PJ_INET6_ADDRSTRLEN);
+ ++idx;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ close(fd);
+ *size = idx;
+ if (idx > 0) {
+ char *final = realloc(deprecatedAddrs,
+ idx*sizeof(char)*PJ_INET6_ADDRSTRLEN);
+ if (final) {
+ *addresses = final;
+ } else {
+ perror("realloc error: abort");
+ free(deprecatedAddrs);
+ }
+ } else {
+ free(deprecatedAddrs);
+ }
+#endif
+}
/*
* Add ICE candidate
@@ -730,6 +883,29 @@ PJ_DEF(pj_status_t) pj_ice_sess_add_cand
unsigned *p_cand_id,
pj_ice_cand_transport transport)
{
+ /**
+ * RFC 2466: an ip address can have the status DEPRECATED and SHOULD NOT
+ * be used by new by applications unless they already use it.
+ * So, we should ignore these addresses.
+ * Also, ips with the TENTATIVE state are not ready and SHOULD NOT be
+ * used for now. Ignore these addresses too.
+ */
+ char* deprecatedAddrs = NULL;
+ size_t size = 0;
+ get_invalid_addresses(&deprecatedAddrs, &size);
+ if (deprecatedAddrs != NULL) {
+ char tmpAddrStr[PJ_INET6_ADDRSTRLEN];
+ pj_sockaddr_print(addr, tmpAddrStr, sizeof(tmpAddrStr), 0);
+ for (int i = 0; i<size*PJ_INET6_ADDRSTRLEN; i+=PJ_INET6_ADDRSTRLEN) {
+ if (!strncmp(tmpAddrStr, &deprecatedAddrs[i], PJ_INET6_ADDRSTRLEN)) {
+ free(deprecatedAddrs);
+ /* This address is considered as deprecated ignore it. */
+ return PJ_SUCCESS;
+ }
+ }
+ free(deprecatedAddrs);
+ }
+
pj_ice_sess_cand *lcand;
pj_status_t status = PJ_SUCCESS;
char address[PJ_INET6_ADDRSTRLEN];