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