]> git.sur5r.net Git - ngadmin/blob - lib/src/session.c
43da03079109458cab993ddd1472b16c6512be4c
[ngadmin] / lib / src / session.c
1
2 #include <errno.h>
3
4 #include <ngadmin.h>
5
6 #include <nsdp/attr.h>
7 #include <nsdp/protocol.h>
8
9 #include "lib.h"
10 #include "network.h"
11
12
13 int ngadmin_scan (struct ngadmin *nga)
14 {
15         int i;
16         List *attr, *swiList;
17         struct swi_attr *sa;
18         struct nsdp_cmd nc;
19         /*
20         sent by official win client:
21         ATTR_PRODUCT,
22         ATTR_UNK2,
23         ATTR_NAME,
24         ATTR_MAC,
25         ATTR_UNK5,
26         ATTR_IP,
27         ATTR_NETMASK,
28         ATTR_GATEWAY,
29         ATTR_DHCP,
30         ATTR_UNK12,
31         ATTR_FIRM_VER,
32         ATTR_UNK14,
33         ATTR_UNK15,
34         ATTR_END
35         */
36         static const unsigned short hello[] = {
37                 ATTR_PRODUCT,
38                 ATTR_NAME,
39                 ATTR_MAC,
40                 ATTR_IP,
41                 ATTR_NETMASK,
42                 ATTR_GATEWAY,
43                 ATTR_DHCP,
44                 ATTR_FIRM_VER,
45                 ATTR_PORTS_COUNT,
46                 ATTR_END
47         };
48         
49         
50         if (nga == NULL)
51                 return ERR_INVARG;
52         
53         free(nga->swi_tab);
54         nga->swi_tab = NULL;
55         nga->swi_count = 0;
56         nga->current = NULL;
57         
58         
59         /* create attributes for an "hello" request */
60         attr = createEmptyList();
61         for (i = 0; ; i++) {
62                 pushBackList(attr, newEmptyAttr(hello[i]));
63                 if (hello[i] == ATTR_END)
64                         break;
65         }
66         
67         /* send request to all potential switches */
68         prepareSend(nga, &nc, CODE_READ_REQ);
69         i = sendNsdpPacket(nga->sock, &nc, attr);
70         clearList(attr, (void(*)(void*))freeAttr);
71         if (i == -EINVAL)
72                 return ERR_INVARG;
73         else if (i < 0)
74                 return ERR_NET;
75         
76         /* try to receive any packets until timeout */
77         swiList = createEmptyList();
78         /* FIXME: end after timeout whatever received packet is good or not */
79         while (1) {
80                 prepareRecv(nga, &nc, CODE_READ_REP);
81                 if (recvNsdpPacket(nga->sock, &nc, attr, &nga->timeout) < 0)
82                         break;
83                 
84                 sa = malloc(sizeof(struct swi_attr));
85                 if (sa == NULL)
86                         return ERR_MEM;
87                 
88                 extractSwitchAttributes(sa, attr);
89                 clearList(attr, (void(*)(void*))freeAttr);
90                 pushBackList(swiList, sa);
91         }
92         
93         nga->swi_count = swiList->count;
94         nga->swi_tab = convertToArray(swiList, sizeof(struct swi_attr));
95         destroyList(swiList, free);
96         destroyList(attr, (void(*)(void*))freeAttr);
97         
98         
99         return ERR_OK;
100 }
101
102
103 const struct swi_attr* ngadmin_getSwitchTab (struct ngadmin *nga, int *nb)
104 {
105         if (nga == NULL || nb == NULL)
106                 return NULL;
107         
108         *nb = nga->swi_count;
109         
110         return nga->swi_tab;
111 }
112
113
114 const struct swi_attr* ngadmin_getCurrentSwitch (struct ngadmin *nga)
115 {
116         if (nga == NULL)
117                 return NULL;
118         
119         return nga->current;
120 }
121
122
123 int ngadmin_login (struct ngadmin *nga, int id)
124 {
125         List *attr;
126         struct attr *at;
127         int ret = ERR_OK;
128         struct swi_attr *sa;
129         
130         
131         if (nga == NULL)
132                 return ERR_INVARG;
133         else if (id < 0 || id >= nga->swi_count)
134                 return ERR_BADID;
135         
136         sa = &nga->swi_tab[id];
137         nga->current = sa;
138         nga->encrypt_pass = false;
139         
140         attr = createEmptyList();
141         pushBackList(attr, newEmptyAttr(ATTR_ENCPASS));
142         ret = readRequest(nga, attr);
143         if (ret != ERR_OK)
144                 goto end;
145         
146         filterAttributes(attr, ATTR_ENCPASS, ATTR_END);
147         if (attr->first != NULL) {
148                 at = attr->first->data;
149                 nga->encrypt_pass = (at->size == 4 && ntohl(*(unsigned int*)at->data) == 1);
150         }
151         clearList(attr, (void(*)(void*))freeAttr);
152         
153         /* Strangely, passwords must never be encrypted inside a read request,
154          * or it will be rejected. Seems more to be a firmware bug. */
155         pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
156         ret = readRequest(nga, attr);
157         if (ret == ERR_OK ) {
158                 /* login succeeded */
159                 /* TODO: if keep broadcasting is disabled, connect() the UDP 
160                 socket so icmp errors messages (port unreachable, TTL exceeded 
161                 in transit, ...) can be received */
162         } else {
163                 /* login failed */
164                 nga->current = NULL;
165         }
166         
167 end:
168         destroyList(attr, (void(*)(void*))freeAttr);
169         
170         
171         return ret;
172 }
173
174