10 #include <sys/ioctl.h>
13 #include <ngadmin.h> /* FIXME */
14 #include <nsdp/protocol.h>
15 #include <nsdp/attr.h>
20 #define MAX_STR_SIZE 64
24 /* read-only properties */
26 unsigned long long recv;
27 unsigned long long sent;
28 unsigned long long crc;
29 /* configurable properties */
38 /* intrinsic properties */
39 unsigned char mac[ETH_ALEN];
40 char product[MAX_STR_SIZE];
41 char firmware[MAX_STR_SIZE];
42 unsigned char ports_count;
44 /* configurable properties */
45 char name[MAX_STR_SIZE];
46 char password[MAX_STR_SIZE];
52 struct port_info *ports;
56 static struct swi_info swi;
60 static int process_read_attr (struct nsdp_cmd *nc, List *attr, struct attr *at)
62 unsigned char p, *byte;
65 struct attr_port_status *apu;
66 struct attr_port_stat *api;
67 struct attr_bitrate *ab;
82 byte = malloc(MAX_STR_SIZE);
83 memcpy(byte, swi.product, MAX_STR_SIZE);
85 at->size = MAX_STR_SIZE;
89 byte = malloc(MAX_STR_SIZE);
90 memcpy(byte, swi.name, MAX_STR_SIZE);
92 at->size = MAX_STR_SIZE;
96 byte = malloc(MAX_STR_SIZE);
97 memcpy(byte, swi.firmware, MAX_STR_SIZE);
99 at->size = MAX_STR_SIZE;
103 byte = malloc(ETH_ALEN);
104 memcpy(byte, swi.mac, ETH_ALEN);
109 case ATTR_PORTS_COUNT:
111 *byte = swi.ports_count;
117 byte = malloc(sizeof(in_addr_t));
118 *(in_addr_t*)byte = swi.ip;
120 at->size = sizeof(in_addr_t);
124 byte = malloc(sizeof(in_addr_t));
125 *(in_addr_t*)byte = swi.netmask;
127 at->size = sizeof(in_addr_t);
131 byte = malloc(sizeof(in_addr_t));
132 *(in_addr_t*)byte = swi.gw;
134 at->size = sizeof(in_addr_t);
138 /* Note: DHCP attribute is special, it is 2 two bytes long
139 * when sent by the switch but only 1 byte long when sent
157 case ATTR_PORT_STATUS:
158 for (p = 0; p < swi.ports_count; p++) {
159 apu = malloc(sizeof(*apu));
161 apu->status = swi.ports[p].state;
164 pushFrontList(attr, newAttr(ATTR_PORT_STATUS, sizeof(*apu), apu));
168 case ATTR_PORT_STATISTICS:
169 for (p = 0; p < swi.ports_count; p++) {
170 api = malloc(sizeof(*api));
171 memset(api, 0, sizeof(*api));
173 api->recv = swi.ports[p].recv;
174 api->sent = swi.ports[p].sent;
176 pushFrontList(attr, newAttr(ATTR_PORT_STATISTICS, sizeof(*api), api));
180 case ATTR_BITRATE_INPUT:
181 for (p = 0; p < swi.ports_count; p++) {
182 ab = malloc(sizeof(*ab));
184 ab->bitrate = swi.ports[p].bitrate_in;
186 pushFrontList(attr, newAttr(ATTR_BITRATE_INPUT, sizeof(*ab), ab));
190 case ATTR_BITRATE_OUTPUT:
191 for (p = 0; p < swi.ports_count; p++) {
192 ab = malloc(sizeof(*ab));
194 ab->bitrate = swi.ports[p].bitrate_out;
196 pushFrontList(attr, newAttr(ATTR_BITRATE_OUTPUT, sizeof(*ab), ab));
206 static int process_write_attr (struct nsdp_cmd *nc, List *attr, struct attr *at)
208 unsigned char p, *byte;
210 struct attr_bitrate *ab;
220 case ATTR_NEW_PASSWORD:
222 passwordEndecode(at->data, at->size);
224 trim(text, MAX_STR_SIZE);
225 strncpy(swi.password, text, MAX_STR_SIZE);
228 case ATTR_STATS_RESET:
229 for (p = 0; p < swi.ports_count; p++) {
230 swi.ports[p].sent = 0;
231 swi.ports[p].recv = 0;
232 swi.ports[p].crc = 0;
237 /* Note: DHCP attribute is special, it is 2 two bytes long
238 * when sent by the switch but only 1 byte long when sent
246 swi.dhcp = (*byte == 1);
252 /* a real switch would accept these modifications, but here we
253 * are not going to mess up the host network settings, so we
254 * refuse these requests
256 nc->error = ERROR_READONLY;
257 nc->attr_error = at->attr;
260 case ATTR_BITRATE_INPUT:
262 if (ab->port > swi.ports_count)
264 swi.ports[ab->port - 1].bitrate_in = ab->bitrate;
267 case ATTR_BITRATE_OUTPUT:
269 if (ab->port > swi.ports_count)
271 swi.ports[ab->port - 1].bitrate_out = ab->bitrate;
280 static int check_password (struct nsdp_cmd *nc, List *attr)
282 ListNode *ln = attr->first;
283 struct attr *at = NULL;
287 /* in a write request, the password attribute must be present
288 * and the first element of the list
289 * official win app never sends password inside a read request, but
290 * ngadmin does that because in that case the password is not echoed
291 * back by the switch, so we have to support that, though password in
292 * such requests are not mandatory
294 if (ln == NULL || (at = ln->data)->attr != ATTR_PASSWORD) {
295 if (nc->code == CODE_WRITE_REQ)
296 nc->error = ERROR_DENIED;
301 nc->error = ERROR_DENIED;
305 /* normally, we would expect password encryption to be handled
306 * in read requests as well as in write requests
307 * but it seems that real Netgear switches that support
308 * password encryption do NOT accept encrypted passwords in
310 * this seems more to be a bug in their firmwares, however, as
311 * the scope of this program is to simulate a switch, we adopt
312 * the same buggy behaviour
314 if (nc->code == CODE_WRITE_REQ && swi.encpass)
315 passwordEndecode(at->data, at->size);
317 text[at->size] = '\0';
318 trim(text, at->size);
319 if (strcmp(text, swi.password) != 0)
320 nc->error = ERROR_DENIED;
324 if (nc->error == 0) {
325 /* correct password */
326 if (ln != NULL && at->attr == ATTR_PASSWORD)
327 destroyElement(attr, ln, (void(*)(void*))freeAttr);
330 /* invalid password, empty list */
331 nc->attr_error = ATTR_PASSWORD;
332 clearList(attr, (void(*)(void*))freeAttr);
338 static void process_packet (struct nsdp_cmd *nc, List *attr)
340 struct ListNode *ln, *pr;
343 int (*process_attr)(struct nsdp_cmd *, List *, struct attr *);
346 check_password(nc, attr);
347 if (nc->code == CODE_READ_REQ) {
348 nc->code = CODE_READ_REP;
349 process_attr = process_read_attr;
350 } else if (nc->code == CODE_WRITE_REQ) {
351 nc->code = CODE_WRITE_REP;
352 process_attr = process_write_attr;
354 /* invalid operation code */
359 for (ln = attr->first; ln != NULL; ) {
362 err = process_attr(nc, attr, at);
365 /* destroy current attribute */
368 destroyElement(attr, pr, (void(*)(void*))freeAttr);
369 } else if (err == 0) {
370 /* keep current attribute */
378 memcpy(&nc->switch_mac, swi.mac, ETH_ALEN);
379 nc->remote_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
381 sendNsdpPacket(sock, nc, attr);
385 static int netdev_info (const char *dev)
391 memset(&ifr, 0, sizeof(struct ifreq));
392 strncpy(ifr.ifr_name, dev, IFNAMSIZ - 1);
394 /* get interface MAC */
395 err = ioctl(sock, SIOCGIFHWADDR, &ifr, sizeof(struct ifreq));
397 perror("ioctl(SIOCGIFHWADDR)");
400 memcpy(swi.mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
402 /* get interface IP */
403 err = ioctl(sock, SIOCGIFADDR, &ifr, sizeof(struct ifreq));
405 perror("ioctl(SIOCGIFADDR)");
408 swi.ip = (*(struct sockaddr_in*)&ifr.ifr_addr).sin_addr.s_addr;
410 /* get interface netmask */
411 err = ioctl(sock, SIOCGIFNETMASK, &ifr, sizeof(struct ifreq));
413 perror("ioctl(SIOCGIFNETMASK)");
416 swi.netmask = (*(struct sockaddr_in*)&ifr.ifr_netmask).sin_addr.s_addr;
418 /* TODO: get netmask */
419 swi.gw = htonl(ntohl(swi.ip & swi.netmask) | 1);
426 static void handler (int sig)
429 printf("interrupt\n");
433 int main (int argc, char **argv)
435 static const struct option options[] = {
436 {"help", no_argument, NULL, 'h'},
437 {"interface", required_argument, NULL, 'i'},
442 const char *iface = "eth0";
443 struct sockaddr_in local;
451 while ((len = getopt_long(argc, argv, "hi:", options, NULL)) != -1) {
455 printf("usage: %s [-h] [-i <interface>]\n", argv[0]);
463 printf("unknown option: \"%s\"\n", argv[optind - 1]);
469 sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
476 memset(&local, 0, sizeof(struct sockaddr_in));
477 local.sin_family = AF_INET;
478 local.sin_addr.s_addr = htonl(INADDR_ANY);
479 local.sin_port = htons(SWITCH_PORT);
481 if (bind(sock, (struct sockaddr*)&local, sizeof(struct sockaddr_in)) < 0) {
487 /* allow broadcasting */
489 len = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &len, sizeof(len));
491 perror("setsockopt(SO_BROADCAST)");
496 /* initialize switch infos */
497 memset(&swi, 0, sizeof(struct swi_info));
498 strncpy(swi.product, "NgEmu_0.1", MAX_STR_SIZE);
499 strncpy(swi.name, "Netgear Switch Emulator", MAX_STR_SIZE);
500 strncpy(swi.firmware, "0.1", MAX_STR_SIZE);
501 strncpy(swi.password, "password", MAX_STR_SIZE);
505 swi.ports = malloc(swi.ports_count * sizeof(struct port_info));
506 memset(swi.ports, 0, swi.ports_count * sizeof(struct port_info));
507 for (p = 0; p < swi.ports_count; p++) {
508 swi.ports[p].state = SPEED_1000_FD;
509 swi.ports[p].pvid = 1;
510 swi.ports[p].bitrate_in = BITRATE_NOLIMIT;
511 swi.ports[p].bitrate_out = BITRATE_NOLIMIT;
512 swi.ports[p].prio = PRIO_NORM;
514 if (netdev_info(iface) < 0)
518 attr = createEmptyList();
520 memset(&sa, 0, sizeof(struct sigaction));
521 sa.sa_handler = handler;
522 sigaction(SIGINT, &sa, NULL);
523 sigaction(SIGTERM, &sa, NULL);
526 memset(&nc, 0, sizeof(struct nsdp_cmd));
527 nc.remote_addr.sin_family = AF_INET;
528 nc.remote_addr.sin_port = htons(CLIENT_PORT);
530 len = recvNsdpPacket(sock, &nc, attr, NULL);
534 /* ignore packets not for us */
535 for (len = 0; nc.switch_mac.ether_addr_octet[len] == 0 && len < ETH_ALEN; len++);
536 if (len < ETH_ALEN && memcmp(swi.mac, &nc.switch_mac, ETH_ALEN) != 0)
539 process_packet(&nc, attr);
540 clearList(attr, (void(*)(void*))freeAttr);
543 destroyList(attr, (void(*)(void*))freeAttr);