really tenacious guy

Force Ekiga 3.x Network Interface Setting

Could not register(Timeout)

As you may already know, new Ekiga versions do not allow setting the network interface to send the requests. This is now controlled by to underlying OPAL library and Ekiga developer does not see any problems. The problems that are caused by sending REGISTERs on all the available interfaces hoping that at least one will make its way to the server.

Update: Now available for download: exposeif.tar.gz. Don’t forget to run ldconfig after installing.

/usr/local/bin/exposeif usage:

    /usr/local/bin/exposeif options program 

Options:
    -i|--interfaces  List of interfaces to expose (comma delimited)
    -d|--debug       Debug output from libexposeif.so
    -h|--help        This help

Example:
    /usr/local/bin/exposeif -i eth0,lo ekiga -d 4
This is not a production-level code. It may cause memory leaks within the application. I am currently working to make it as reliable as possible. As always, standard disclaimer applies.

Bug 553595 – cannot connect to Asterisk server
Damien Sandras (ekiga developer):
We tend to automate things at maximum, so I don’t think it is possible. Perhaps in 3.2 we will reintroduce a setting, but in that case if you listen only on one interface, there is no way to connect through a VPN and to the Internet at the same time.

I’ll discuss with Robert, but I think the problem is on Asterisk side. One thing we could improve is that as soon we get an answer for one interface, we do not try others.

ALL of my computers are no longer able to register to my work PBX with this “feature” so I decided to hack it.

Basically, all what I need is to expose one network interface to Ekiga so that it does not start sending bogus data through other ones.

The answer is… ioctl wrapping done previously for my Motorola A1200 camera

Meanwhile here is the quick and dirty source:

// Roman Yepishev, blog.rtg.in.ua
// [email protected]
#define _GNU_SOURCE
#include <dlfcn.h>
#include <string.h>
#include <sys/socket.h>
#include <linux/sockios.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <net/if.h>
#include <unistd.h>

static int (*next_ioctl)(int fd, int request, void *data) = NULL;

int ioctl(int fd, int request, void *data)
{
        char *msg;
        if (next_ioctl == NULL) {
                fprintf(stderr, "ioctl : wrapping ioctl\n");
                fflush(stderr);
                next_ioctl = dlsym(RTLD_NEXT, "ioctl");
                fprintf(stderr, "next_ioctl = %p\n", next_ioctl);
                fflush(stderr);
                if ((msg = dlerror()) != NULL) {
                        fprintf(stderr, "ioctl: dlopen failed : %s\n", msg);
                        fflush(stderr);
                        exit(1);
                } else
                        fprintf(stderr, "ioctl: wrapping done\n");
                fflush(stderr);
        }

        if (request == SIOCGIFCONF) {
            static struct ifreq ifreqs_in[20];
            static struct ifreq ifreqs_out[2];

            int rval, nifaces = 0, i = 0;
            int fi = 0;

            struct ifconf ifconf_in;
            struct ifconf ifconf_out;

            memset(&ifconf_in,0,sizeof(struct ifconf));
            memset(&ifconf_out,0,sizeof(struct ifconf));
            
            ifconf_in.ifc_buf = (char*) (ifreqs_in);
            ifconf_in.ifc_len = sizeof(ifreqs_in);

            if ((rval = next_ioctl(fd, request, &ifconf_in)) < 0) {
                // nothing to do here, sorry.
                return rval;
            }

            nifaces = ifconf_in.ifc_len / sizeof(struct ifreq);

            fprintf(stderr, "Interfaces: (count = %d):\n", nifaces);

            for (i = 0; i < nifaces; i++) {
                fprintf(stderr, "\t%-10s\n", ifreqs_in[i].ifr_name);
                // Interfaces to expose
                if (! strcmp(ifreqs_in[i].ifr_name, "ath0") || ! strcmp(ifreqs_in[i].ifr_name, "lo")) {
                    // need to copy it to ifconf_out
                    fprintf(stderr, "Copying interface %s (in[%d] -> out[%d])\n", ifreqs_in[i].ifr_name, i, fi);
                    memcpy(&ifreqs_out[fi], &ifreqs_in[i], sizeof(struct ifreq));
                    fprintf(stderr, "Copied? - %s\n", ifreqs_out[fi].ifr_name);
                    fi++;
                }
            }

            ifconf_out.ifc_req = ifreqs_out;
            ifconf_out.ifc_len = fi * sizeof(struct ifreq);

            fprintf(stderr, "ifc_len = %d\nFixed list:\n", fi);

            nifaces = ifconf_out.ifc_len / sizeof(struct ifreq);

            fprintf(stderr, "Interfaces: (count = %d):\n", nifaces);

            for (i = 0; i < nifaces; i++) {
                fprintf(stderr, "\t%-10s\n", ifreqs_out[i].ifr_name);
            }

            memcpy(data, &ifconf_out, sizeof(struct ifconf));

            return rval;

        }

        return next_ioctl(fd, request, data);
}
Compile
gcc -o exposeif.so -ldl -shared exposeif.c
And run:
LD_PRELOAD=./exposeif.so /usr/bin/ekiga
Okay, this is a hack, but it works.

See also

Comments