]> git.sur5r.net Git - ngadmin/blobdiff - lib/src/session.c
Lib: fallback to login with write request when read request fails
[ngadmin] / lib / src / session.c
index c36c772d899a05587f58dd9fd15cf0e8a4cab2ec..a0357f3ba4a2d356a6639df90222ed937098c49f 100644 (file)
@@ -3,8 +3,8 @@
 
 #include <ngadmin.h>
 
-#include <attr.h>
-#include <protocol.h>
+#include <nsdp/attr.h>
+#include <nsdp/protocol.h>
 
 #include "lib.h"
 #include "network.h"
@@ -15,23 +15,28 @@ int ngadmin_scan (struct ngadmin *nga)
        int i;
        List *attr, *swiList;
        struct swi_attr *sa;
-       /*
-       sent by official win client:
-       ATTR_PRODUCT,
-       ATTR_UNK2,
-       ATTR_NAME,
-       ATTR_MAC,
-       ATTR_UNK5,
-       ATTR_IP,
-       ATTR_NETMASK,
-       ATTR_GATEWAY,
-       ATTR_DHCP,
-       ATTR_UNK12,
-       ATTR_FIRM_VER,
-       ATTR_UNK14,
-       ATTR_UNK15,
-       ATTR_END
-       */
+       struct nsdp_cmd nc;
+       /* sent by official win client:
+        * ATTR_PRODUCT
+        * ATTR_UNK2
+        * ATTR_NAME
+        * ATTR_MAC
+        * ATTR_UNK5
+        * ATTR_IP
+        * ATTR_NETMASK
+        * ATTR_GATEWAY
+        * ATTR_DHCP
+        * ATTR_UNK12
+        * ATTR_FIRM_VER
+        * ATTR_UNK14
+        * ATTR_UNK15
+        * ATTR_END
+        *
+        * one may be tempted to add ATTR_ENCPASS so we can now early if the
+        * switch uses password encryption, but this would cause (at least)
+        * switches that do not support this feature not to reply to the
+        * discovery request at all
+        */
        static const unsigned short hello[] = {
                ATTR_PRODUCT,
                ATTR_NAME,
@@ -64,7 +69,8 @@ int ngadmin_scan (struct ngadmin *nga)
        }
        
        /* send request to all potential switches */
-       i = sendNsdpPacket(nga, CODE_READ_REQ, attr);
+       prepareSend(nga, &nc, CODE_READ_REQ);
+       i = sendNsdpPacket(nga->sock, &nc, attr);
        clearList(attr, (void(*)(void*))freeAttr);
        if (i == -EINVAL)
                return ERR_INVARG;
@@ -74,13 +80,19 @@ int ngadmin_scan (struct ngadmin *nga)
        /* try to receive any packets until timeout */
        swiList = createEmptyList();
        /* FIXME: end after timeout whatever received packet is good or not */
-       while (recvNsdpPacket(nga, CODE_READ_REP, NULL, NULL, attr) >= 0) {
+       while (1) {
+               prepareRecv(nga, &nc, CODE_READ_REP);
+               if (recvNsdpPacket(nga->sock, &nc, attr, &nga->timeout) < 0)
+                       break;
+               
                sa = malloc(sizeof(struct swi_attr));
                if (sa == NULL)
                        return ERR_MEM;
-               extractSwitchAttributes(sa, attr);
+               
+               if (extractSwitchAttributes(sa, attr) == 0)
+                       pushBackList(swiList, sa);
+               
                clearList(attr, (void(*)(void*))freeAttr);
-               pushBackList(swiList, sa);
        }
        
        nga->swi_count = swiList->count;
@@ -130,6 +142,10 @@ int ngadmin_login (struct ngadmin *nga, int id)
        nga->current = sa;
        nga->encrypt_pass = false;
        
+       /* determine if the switch uses password encryption
+        * as explained in ngadmin_scan, it cannot be done at discovery
+        * stage
+        */
        attr = createEmptyList();
        pushBackList(attr, newEmptyAttr(ATTR_ENCPASS));
        ret = readRequest(nga, attr);
@@ -139,19 +155,30 @@ int ngadmin_login (struct ngadmin *nga, int id)
        filterAttributes(attr, ATTR_ENCPASS, ATTR_END);
        if (attr->first != NULL) {
                at = attr->first->data;
-               nga->encrypt_pass = (at->size == 4 && ntohl(*(unsigned int*)at->data) == 1);
+               nga->encrypt_pass = (at->size == 4 && *(unsigned int*)at->data == 1);
        }
        clearList(attr, (void(*)(void*))freeAttr);
        
-       /* Strangely, passwords must never be encrypted inside a read request,
-        * or it will be rejected. Seems more to be a firmware bug. */
+       /* strangely, passwords must never be encrypted inside a read request,
+        * or it will be rejected. Seems more to be a firmware bug
+        */
        pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
        ret = readRequest(nga, attr);
+       
+       if (ret == ERR_INVOP) {
+               /* it seems some switches do not support login with read request
+                * fallback to write request, even if it has the drawback of
+                * the password being broadcasted back by the switch
+                */
+               ret = writeRequest(nga, NULL);
+       }
+       
        if (ret == ERR_OK ) {
                /* login succeeded */
-               /* TODO: if keep broadcasting is disabled, connect() the UDP 
-               socket so icmp errors messages (port unreachable, TTL exceeded 
-               in transit, ...) can be received */
+               /* TODO: if keep broadcasting is disabled, connect() the UDP
+                * socket so icmp errors messages (port unreachable, TTL exceeded
+                * in transit, ...) can be received
+                */
        } else {
                /* login failed */
                nga->current = NULL;