Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

TivoBeacon port (2190)

Help
markens
2011-02-17
2013-05-29
  • markens
    markens
    2011-02-17

    I am starting to use minidlna (v1.0.18.2) on TomatoUSB router firmware.  It works great, although I have a question about how minidlna handles the TivoBeacon port udp/2190.  When looking at netstat after minidlna has been running a while, it's clear that the receive queue on that socket is building up with broadcast packets from other Tivos on the net, and the socket is never being read by minidlna.  Looking at the code confirms this: the socket is used for outgoing broadcast packets only.

    I imagine the queue will eventually fill and further packets will simply be dropped, which is obviously not a problem for minidlna.  But this doesn't seem very clean.  Shouldn't the code read and clear the socket to keep the queue empty?  Just curious about whether this behavior is intentional or a bug.

    Thanks much.  All else works great, including using with dlna clients!

     
  • Justin Maggard
    Justin Maggard
    2011-02-17

    Oh, you're right… that's a bug.  Thanks for pointing that out!  Guess I never got around to hooking that up.  I just checked in code to fix that.  Let me know if you run into any issues with the latest update.

     
  • markens
    markens
    2011-02-17

    Quick fix, thanks.  I took a quick look through the changes (which look good), but have not run them yet.

    This brings up another issue I'm having (still using v1.0.18.2):

    When starting minidlna (with tivo support enabled) on my tomatousb router, the two tivos on my LAN did not see the broadcast beacon.  Debugging showed minidlna was using the default broadcast address of 255.255.255.255, and it was routed out my WAN if instead of LAN if (and so tivos didn't see it).  There is no "broadcast address"  debug line output, which is in line with what I'm seeing.

    Not sure why minidlna didn't find the correct bcast address.  Interfaces are configured correctly; here's info from netstat for br0 interface (/etc/minidlna.conf config: "network_interface=br0"):

    br0        Link encap:Ethernet  HWaddr E0:91:xx:xx:xx:xx
               inet addr:172.22.0.3  Bcast:172.22.0.255  Mask:255.255.255.0
               inet6 addr: 2001:xxxxxxxxxx::1/64 Scope:Global
               inet6 addr: fe80::e291:xxff:fexx:xxxx/64 Scope:Link
               UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
    

    Could ipv6 addresses on the if cause an issue?  It would be hard to back these out on my router at this point to test.

    Anything else I should verify?  Very curious.

    Thanks…

     
  • Justin Maggard
    Justin Maggard
    2011-02-17

    No, I can't think of any reason that wouldn't work.  Very curious indeed.  I also have ipv6 addresses on my wireless interface, and it works fine for me.  I just checked in code to at least log the error if that ioctl fails, so we should get a better idea if you can build out of cvs.

     
  • markens
    markens
    2011-02-18

    Thanks.  I don't have a tomato build environment currently set up, so I'll have to defer further tests until I can find some time to do that.  Another project for the list…

     
  • markens
    markens
    2011-02-19

    Found the bcast address issue with debugging help from teddy_b, discussed in tomatousb forum thread with pertinent info starting here.

    Problem turns out to be that indexes for the interface entries fetched by SIOCGIFNAME are not necessarily contiguous.  Mine fails at i=4 (before finding the correct interface), and so the break exits the loop.

    Teddy_b wrote a test routine based on the minidlna getBcastAddress route and put in lots of debugging printfs to trace behavior.   His method is to use /proc/net/dev to find the device names, and it now finds the correct bcast address in my case.

    Attached is the test routine FYI.  Thanks!

    static uint32_t
    getBcastAddress(void)
    {
        int rval;
        int s = socket(PF_INET, SOCK_STREAM, 0);
        struct sockaddr_in sin;
        struct sockaddr_in addr;
        struct ifreq ifr;
        FILE * f;
        char buf[256], *p;
        if (s < 0) {
            printf("error on socket open [%s]\n", strerror(errno));
            return INADDR_BROADCAST;
        }
        f = fopen("/proc/net/dev", "r");
        if (!f) {
            printf("error opening /proc/net/dev [%s]\n", strerror(errno));
            close(s);
            return INADDR_BROADCAST;
        }
        // skip 2-line header
        fgets(buf, sizeof(buf), f);
        fgets(buf, sizeof(buf), f);
        while (fgets(buf, sizeof(buf), f)) {
            if ((p = strchr(buf, ':')) == NULL) continue;
            *p = 0;
            // skip leading spaces
            if ((p = strrchr(buf, ' ')) == NULL) p = buf;
            else ++p;
            strncpy(ifr.ifr_name, p, IFNAMSIZ);
            printf("Checking %s...\n", ifr.ifr_name);
            if(ioctl(s, SIOCGIFADDR, &ifr, sizeof(struct ifreq)) < 0) {
                printf("Failed to get IFADDR on %s [%s]\n", ifr.ifr_name, strerror(errno));
                continue;
            }
            memcpy(&addr, &ifr.ifr_addr, sizeof(addr));
            printf("Considering dev %s [%s]\n",
                ifr.ifr_name, inet_ntoa(addr.sin_addr));
            if(strcmp(inet_ntoa(addr.sin_addr), lan_addr) == 0)
            {
                printf("  Checking IFBRDADDR...\n");
                rval = ioctl(s, SIOCGIFBRDADDR, &ifr);
                if( rval < 0 )
                {
                    printf("Failed to get broadcast addr on %s [%s]\n", ifr.ifr_name, strerror(errno));
                    close(s);
                    fclose(f);
                    return INADDR_BROADCAST;
                }
                memcpy(&sin, &ifr.ifr_broadaddr, sizeof(sin));
                close(s);
                fclose(f);
                printf("Interface: %s broadcast addr %s\n", ifr.ifr_name, inet_ntoa(sin.sin_addr));
                return ntohl((uint32_t)(sin.sin_addr.s_addr));
            }
        }
        printf("Nothing found; using default\n");
        fclose(f);
        close(s);
        return INADDR_BROADCAST;
    }
    
     
  • Justin Maggard
    Justin Maggard
    2011-02-20

    Very interesting… I wasn't aware that could happen.  I'd rather avoid using proc in fixing this bug, because I'm trying to keep all future changes portable for the eventual complete port to OSX / BSD.  I just checked in a different change that I believe will resolve the issue in a more portable way.  Would you be able to try it out?

     
  • markens
    markens
    2011-02-21

    We used your new getBcastAddress() code (with SIOCGIFCONF) in our test program, and it worked as expected.  Looks good.

    A couple minor bugs we noticed in the latest tivo_beacon.c (rev 1.8):

    - line 118: extraneous copy/paste arg to DPRINTF

    - socket s not closed in several return paths (lines 119, 142)

    Thanks again.

     
  • Justin Maggard
    Justin Maggard
    2011-02-22

    Thanks for pointing out those bugs.  Fixes checked in.  Guess that'll teach me to check in code that late at night. ;)