#include <ngadmin.h>
-#include <attr.h>
-#include <protocol.h>
+#include <nsdp/attr.h>
+#include <nsdp/protocol.h>
#include "lib.h"
#include "network.h"
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,
}
/* 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;
/* 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;
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);
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;