Ignore:
Timestamp:
May 1, 2010, 4:21:41 AM (11 years ago)
Author:
charles
Message:

(1.9x third-party) upgrade our miniupnp snapshot for #3125 "UPnP fails on Linksys AM300 modem/router"

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/1.9x/third-party/miniupnp/miniupnpc.c

    r10285 r10578  
    1 /* $Id: miniupnpc.c,v 1.74 2010/01/09 23:54:40 nanard Exp $ */
     1/* $Id: miniupnpc.c,v 1.80 2010/04/12 20:39:41 nanard Exp $ */
    22/* Project : miniupnp
    33 * Author : Thomas BERNARD
     
    1515#define __BSD_VISIBLE 1
    1616#endif
    17 #endif
    18 
    19 #ifdef __APPLE__
    20 #define _DARWIN_C_SOURCE
    2117#endif
    2218
     
    5147#include <netinet/in.h>
    5248#include <arpa/inet.h>
     49#include <netdb.h>
    5350#if !defined(__amigaos__) && !defined(__amigaos4__)
    5451#include <poll.h>
    5552#endif
    56 #include <netdb.h>
    5753#include <strings.h>
    5854#include <errno.h>
     
    7470#include "minixml.h"
    7571#include "upnpcommands.h"
     72#include "connecthostport.h"
    7673
    7774#ifdef WIN32
     
    172169}
    173170
    174 /* simpleUPnPcommand :
     171/* simpleUPnPcommand2 :
    175172 * not so simple !
    176173 * return values :
    177174 *   0 - OK
    178175 *  -1 - error */
    179 int simpleUPnPcommand(int s, const char * url, const char * service,
    180                       const char * action, struct UPNParg * args,
    181                       char * buffer, int * bufsize)
    182 {
    183         struct sockaddr_in dest;
     176static int simpleUPnPcommand2(int s, const char * url, const char * service,
     177                       const char * action, struct UPNParg * args,
     178                       char * buffer, int * bufsize, const char * httpversion)
     179{
    184180        char hostname[MAXHOSTNAMELEN+1];
    185181        unsigned short port = 0;
     
    191187    int n;
    192188        int contentlen, headerlen;      /* for the response */
    193 #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
    194         struct timeval timeout;
    195 #endif
     189
    196190        snprintf(soapact, sizeof(soapact), "%s#%s", service, action);
    197191        if(args==NULL)
     
    262256        if(s<0)
    263257        {
    264                 s = socket(PF_INET, SOCK_STREAM, 0);
    265                 if(s<0)
     258                s = connecthostport(hostname, port);
     259                if(s < 0)
    266260                {
    267                         PRINT_SOCKET_ERROR("socket");
    268261                        *bufsize = 0;
    269262                        return -1;
    270263                }
    271 #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
    272                 /* setting a 3 seconds timeout for the connect() call */
    273                 timeout.tv_sec = 3;
    274                 timeout.tv_usec = 0;
    275                 if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0)
    276                 {
    277                         PRINT_SOCKET_ERROR("setsockopt");
    278                 }
    279                 timeout.tv_sec = 3;
    280                 timeout.tv_usec = 0;
    281                 if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0)
    282                 {
    283                         PRINT_SOCKET_ERROR("setsockopt");
    284                 }
    285 #endif
    286                 dest.sin_family = AF_INET;
    287                 dest.sin_port = htons(port);
    288                 dest.sin_addr.s_addr = inet_addr(hostname);
    289         n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr));
    290 #ifdef MINIUPNPC_IGNORE_EINTR
    291         while(n < 0 && errno == EINTR)
    292                 {
    293                         socklen_t len;
    294                         fd_set wset;
    295                         int err;
    296                         FD_ZERO(&wset);
    297                         FD_SET(s, &wset);
    298                         if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR)
    299                                 continue;
    300                         /*len = 0;*/
    301                         /*n = getpeername(s, NULL, &len);*/
    302                         len = sizeof(err);
    303                         if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) {
    304                                 PRINT_SOCKET_ERROR("getsockopt");
    305                                 closesocket(s);
    306                                 return -1;
    307                         }
    308                         if(err != 0) {
    309                                 errno = err;
    310                                 n = -1;
    311                         } else {
    312                                 n = 0;
    313                         }
    314                 }
    315 #endif
    316                 if(n < 0)
    317         {
    318                         PRINT_SOCKET_ERROR("connect");
    319                         closesocket(s);
    320                         *bufsize = 0;
    321                         return -1;
    322                 }
    323         }
    324 
    325         n = soapPostSubmit(s, path, hostname, port, soapact, soapbody);
     264        }
     265
     266        n = soapPostSubmit(s, path, hostname, port, soapact, soapbody, httpversion);
    326267        if(n<=0) {
    327268#ifdef DEBUG
     
    354295        closesocket(s);
    355296        return 0;
     297}
     298
     299/* simpleUPnPcommand :
     300 * not so simple !
     301 * return values :
     302 *   0 - OK
     303 *  -1 - error */
     304int simpleUPnPcommand(int s, const char * url, const char * service,
     305                       const char * action, struct UPNParg * args,
     306                       char * buffer, int * bufsize)
     307{
     308        int result;
     309        int origbufsize = *bufsize;
     310
     311        result = simpleUPnPcommand2(s, url, service, action, args, buffer, bufsize, "1.0");
     312        if (result < 0 || *bufsize == 0)
     313        {
     314#ifdef DEBUG
     315            printf("Error or no result from SOAP request; retrying with HTTP/1.1\n");
     316#endif
     317                *bufsize = origbufsize;
     318                result = simpleUPnPcommand2(s, url, service, action, args, buffer, bufsize, "1.1");
     319        }
     320        return result;
    356321}
    357322
     
    451416        int sudp;
    452417        int n;
    453         struct sockaddr_in sockudp_r, sockudp_w;
     418        struct sockaddr sockudp_r;
    454419        unsigned int mx;
     420        int rv;
     421        struct addrinfo hints, *servinfo, *p;
    455422#ifdef WIN32
    456423        /*MIB_IPFORWARDROW ip_forward;*/
     
    482449                return NULL;
    483450        }
    484     /* reception */
    485     memset(&sockudp_r, 0, sizeof(struct sockaddr_in));
    486     sockudp_r.sin_family = AF_INET;
    487         if(sameport)
    488         sockudp_r.sin_port = htons(PORT);
    489     sockudp_r.sin_addr.s_addr = INADDR_ANY;
    490     /* emission */
    491     memset(&sockudp_w, 0, sizeof(struct sockaddr_in));
    492     sockudp_w.sin_family = AF_INET;
    493     sockudp_w.sin_port = htons(PORT);
    494     sockudp_w.sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR);
     451        /* reception */
     452        memset(&sockudp_r, 0, sizeof(struct sockaddr));
     453        if(0/*ipv6*/) {
     454                struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_r;
     455                p->sin6_family = AF_INET6;
     456                if(sameport)
     457                        p->sin6_port = htons(PORT);
     458                p->sin6_addr = in6addr_any;//IN6ADDR_ANY_INIT;/*INADDR_ANY;*/
     459        } else {
     460                struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_r;
     461                p->sin_family = AF_INET;
     462                if(sameport)
     463                        p->sin_port = htons(PORT);
     464                p->sin_addr.s_addr = INADDR_ANY;
     465        }
     466#if 0
     467        /* emission */
     468        memset(&sockudp_w, 0, sizeof(struct sockaddr_in));
     469        sockudp_w.sin_family = AF_INET;
     470        sockudp_w.sin_port = htons(PORT);
     471        sockudp_w.sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR);
     472#endif
    495473#ifdef WIN32
    496474/* This code could help us to use the right Network interface for
     
    547525                struct in_addr mc_if;
    548526                mc_if.s_addr = inet_addr(multicastif);
    549         sockudp_r.sin_addr.s_addr = mc_if.s_addr;
     527                if(0/*ipv6*/) {
     528                } else {
     529                        ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr;
     530                }
    550531                if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0)
    551532                {
     
    555536
    556537        /* Avant d'envoyer le paquet on bind pour recevoir la reponse */
    557     if (bind(sudp, (struct sockaddr *)&sockudp_r, sizeof(struct sockaddr_in)) != 0)
     538    if (bind(sudp, &sockudp_r, 0/*ipv6*/?sizeof(struct sockaddr_in6):sizeof(struct sockaddr_in)) != 0)
    558539        {
    559540        PRINT_SOCKET_ERROR("bind");
     
    573554                             MSearchMsgFmt, deviceList[deviceIndex++], mx);
    574555                /*printf("Sending %s", bufr);*/
     556#if 0
    575557                n = sendto(sudp, bufr, n, 0,
    576558                           (struct sockaddr *)&sockudp_w, sizeof(struct sockaddr_in));
    577559                if (n < 0) {
    578560                        PRINT_SOCKET_ERROR("sendto");
     561                        closesocket(sudp);
     562                        return devlist;
     563                }
     564#endif
     565                memset(&hints, 0, sizeof(hints));
     566                hints.ai_family = AF_UNSPEC; // AF_INET6 or AF_INET
     567                hints.ai_socktype = SOCK_DGRAM;
     568                /*hints.ai_flags = */
     569                if ((rv = getaddrinfo(UPNP_MCAST_ADDR, XSTR(PORT), &hints, &servinfo)) != 0) {
     570#ifdef WIN32
     571                    fprintf(stderr, "getaddrinfo() failed: %d\n", rv);
     572#else
     573                    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
     574#endif
     575                    return devlist;
     576                }
     577                for(p = servinfo; p; p = p->ai_next) {
     578                        n = sendto(sudp, bufr, n, 0, p->ai_addr, p->ai_addrlen);
     579                        if (n < 0) {
     580                                PRINT_SOCKET_ERROR("sendto");
     581                                continue;
     582                        }
     583                }
     584                freeaddrinfo(servinfo);
     585                if(n < 0) {
    579586                        closesocket(sudp);
    580587                        return devlist;
     
    603610                if(st&&descURL)
    604611                {
    605                         /*printf("M-SEARCH Reply:\nST: %.*s\nLocation: %.*s\n",
    606                                stsize, st, urlsize, descURL); */
     612#ifdef DEBUG
     613                        printf("M-SEARCH Reply:\nST: %.*s\nLocation: %.*s\n",
     614                               stsize, st, urlsize, descURL);
     615#endif
     616                        for(tmp=devlist; tmp; tmp = tmp->pNext) {
     617                                if(memcmp(tmp->descURL, descURL, urlsize) == 0 &&
     618                                   tmp->descURL[urlsize] == '\0' &&
     619                                   memcmp(tmp->st, st, stsize) == 0 &&
     620                                   tmp->st[stsize] == '\0')
     621                                        break;
     622                        }
     623                        /* at the exit of the loop above, tmp is null if
     624                         * no duplicate device was found */
     625                        if(tmp)
     626                                continue;
    607627                        tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize);
    608628                        tmp->pNext = devlist;
     
    667687        n1 += 2;        /* 1 byte more for Null terminator, 1 byte for '/' if needed */
    668688        n2 = n1; n3 = n1;
    669         n1 += strlen(data->scpdurl);
    670         n2 += strlen(data->controlurl);
    671         n3 += strlen(data->controlurl_CIF);
     689        n1 += strlen(data->first.scpdurl);
     690        n2 += strlen(data->first.controlurl);
     691        n3 += strlen(data->CIF.controlurl);
    672692
    673693        urls->ipcondescURL = (char *)malloc(n1);
     
    684704        strncpy(urls->controlURL_CIF, urls->ipcondescURL, n3);
    685705       
    686         url_cpy_or_cat(urls->ipcondescURL, data->scpdurl, n1);
    687 
    688         url_cpy_or_cat(urls->controlURL, data->controlurl, n2);
    689 
    690         url_cpy_or_cat(urls->controlURL_CIF, data->controlurl_CIF, n3);
    691 
    692 #ifdef DEBUG
    693         printf("urls->ipcondescURL='%s' %d n1=%d\n", urls->ipcondescURL,
    694                strlen(urls->ipcondescURL), n1);
    695         printf("urls->controlURL='%s' %d n2=%d\n", urls->controlURL,
    696                strlen(urls->controlURL), n2);
    697         printf("urls->controlURL_CIF='%s' %d n3=%d\n", urls->controlURL_CIF,
    698                strlen(urls->controlURL_CIF), n3);
     706        url_cpy_or_cat(urls->ipcondescURL, data->first.scpdurl, n1);
     707
     708        url_cpy_or_cat(urls->controlURL, data->first.controlurl, n2);
     709
     710        url_cpy_or_cat(urls->controlURL_CIF, data->CIF.controlurl, n3);
     711
     712#ifdef DEBUG
     713        printf("urls->ipcondescURL='%s' %u n1=%d\n", urls->ipcondescURL,
     714               (unsigned)strlen(urls->ipcondescURL), n1);
     715        printf("urls->controlURL='%s' %u n2=%d\n", urls->controlURL,
     716               (unsigned)strlen(urls->controlURL), n2);
     717        printf("urls->controlURL_CIF='%s' %u n3=%d\n", urls->controlURL_CIF,
     718               (unsigned)strlen(urls->controlURL_CIF), n3);
    699719#endif
    700720}
     
    769789        unsigned int uptime;
    770790        status[0] = '\0';
    771         UPNP_GetStatusInfo(urls->controlURL, data->servicetype,
     791        UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype,
    772792                           status, &uptime, NULL);
    773793        if(0 == strcmp("Connected", status))
     
    826846                                free(descXML);
    827847                                descXML = NULL;
    828                                 if(0==strcmp(data->servicetype_CIF,
     848                                if(0==strcmp(data->CIF.servicetype,
    829849                                   "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")
    830850                                   || state >= 3 )
     
    840860                                        return state;
    841861                                  FreeUPNPUrls(urls);
     862                                  if(data->second.servicetype[0] != '\0') {
     863#ifdef DEBUG
     864                                    printf("We tried %s, now we try %s !\n",
     865                                           data->first.servicetype, data->second.servicetype);
     866#endif
     867                                    /* swaping WANPPPConnection and WANIPConnection ! */
     868                                    memcpy(&data->tmp, &data->first, sizeof(struct IGDdatas_service));
     869                                    memcpy(&data->first, &data->second, sizeof(struct IGDdatas_service));
     870                                    memcpy(&data->second, &data->tmp, sizeof(struct IGDdatas_service));
     871                                    GetUPNPUrls(urls, data, dev->descURL);
     872#ifdef DEBUG
     873                                    printf("UPNPIGD_IsConnected(%s) = %d\n",
     874                                       urls->controlURL,
     875                                   UPNPIGD_IsConnected(urls, data));
     876#endif
     877                                    if((state >= 2) || UPNPIGD_IsConnected(urls, data))
     878                                          return state;
     879                                    FreeUPNPUrls(urls);
     880                                  }
    842881                                }
    843882                                memset(data, 0, sizeof(struct IGDdatas));
Note: See TracChangeset for help on using the changeset viewer.