mrpd: comment cleanup
[profile/ivi/OpenAVB.git] / daemons / mrpd / mrpw.c
1 /******************************************************************************
2
3   Copyright (c) 2012, Intel Corporation 
4   Copyright (c) 2012, AudioScience, Inc
5   All rights reserved.
6   
7   Redistribution and use in source and binary forms, with or without 
8   modification, are permitted provided that the following conditions are met:
9   
10    1. Redistributions of source code must retain the above copyright notice, 
11       this list of conditions and the following disclaimer.
12   
13    2. Redistributions in binary form must reproduce the above copyright 
14       notice, this list of conditions and the following disclaimer in the 
15       documentation and/or other materials provided with the distribution.
16   
17    3. Neither the name of the Intel Corporation nor the names of its 
18       contributors may be used to endorse or promote products derived from 
19       this software without specific prior written permission.
20   
21   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
23   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
24   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
25   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
26   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
27   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
28   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
29   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
30   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31   POSSIBILITY OF SUCH DAMAGE.
32
33 ******************************************************************************/
34 /*
35  * Main code for Windows implementation of MRP/MMRP/MVRP/MSRP
36  */
37
38 #include <stdio.h>
39 #include <stdlib.h>
40
41 #include <pcap.h>
42 #include <winsock2.h>
43 #include <iphlpapi.h>
44
45 #include "mrpd.h"
46 #include "mrp.h"
47 #include "mvrp.h"
48 #include "msrp.h"
49 #include "mmrp.h"
50
51 #include "que.h"
52
53 #define TIME_PERIOD_100_MILLISECONDS 100
54 #define NETIF_TIMEOUT (-2)
55
56 /* local structs */
57 struct wtimer {
58         int running;
59         int elapsed;
60         unsigned int count;
61         unsigned int interval;
62         unsigned int start_time;
63 };
64
65 struct netif {
66         //pcap version
67         pcap_if_t *alldevs;
68         pcap_if_t *d;
69         uint8_t mac[6];
70         int inum;
71         int i;
72         int error;
73         pcap_t *pcap_interface;
74         char errbuf[PCAP_ERRBUF_SIZE];
75         struct bpf_program fcode;
76         struct pcap_pkthdr *header;
77         const u_char *ethernet_frame;
78         uint8_t tx_frame[1500]; // ethernet frame used to send packets
79 };
80
81 enum {
82         pkt_event_wpcap,
83         pkt_event_localhost,
84         pkt_event_wpcap_timeout,
85         pkt_event_localhost_timeout,
86         app_event_kill_all,
87         loop_time_tick
88 };
89
90 /* global mgmt parameters */
91 int daemonize;
92 int mmrp_enable;
93 int mvrp_enable;
94 int msrp_enable;
95 int logging_enable;
96 int mrpd_port;
97 HANDLE pkt_events[6];
98 HANDLE sem_kill_wpcap_thread;
99 HANDLE sem_kill_localhost_thread;
100 struct que_def *que_wpcap;
101 struct que_def *que_localhost;
102
103 //char *net_interface;
104 int interface_fd;
105
106 /* state machine controls */
107 int periodic_enable;
108 int registration;
109
110 /* if registration is FIXED or FORBIDDEN
111  * updates from MRP are discarded, and
112  * only IN and JOININ messages are sent
113  */
114
115 int participant;
116
117 /* if participant role is 'SILENT' (or non-participant)
118  * applicant doesn't send any messages - configured per-attribute
119  */
120
121 #define VERSION_STR     "0.0"
122
123 static const char *version_str =
124     "mrpw v" VERSION_STR "\n" "Copyright (c) 2012, AudioScience Inc\n";
125
126 unsigned char STATION_ADDR[] = { 0x00, 0x88, 0x77, 0x66, 0x55, 0x44 };
127
128 /* global variables */
129 SOCKET control_socket;
130 extern SOCKET mmrp_socket;
131 extern SOCKET mvrp_socket;
132 extern SOCKET msrp_socket;
133 struct netif *net_if;
134
135 HTIMER periodic_timer;
136 HTIMER gc_timer;
137 HTIMER timer_check_tick;
138
139 extern struct mmrp_database *MMRP_db;
140 extern struct mvrp_database *MVRP_db;
141 extern struct msrp_database *MSRP_db;
142
143 struct netif *netif_open(int timeout_ms)
144 {
145         int inum = 0;
146         int i = 0, total_interfaces = 0;
147         struct netif *netif;
148         IP_ADAPTER_INFO *AdapterInfo;
149         IP_ADAPTER_INFO *Current;
150         ULONG AIS;
151         DWORD status;
152
153         netif = (struct netif *)calloc(1, sizeof(struct netif));
154
155         /* Retrieve the device list on the local machine */
156         if (pcap_findalldevs(&netif->alldevs, netif->errbuf) == -1) {
157                 printf("Error finding interfaces\n");
158                 goto error_return;
159         }
160
161         /* Print the list */
162         for (netif->d = netif->alldevs; netif->d; netif->d = netif->d->next) {
163                 /*printf("%d. %s", ++i, d->name); */
164                 printf("%d", ++i);
165                 if (netif->d->description)
166                         printf(" (%-70s)\n", netif->d->description);
167                 else
168                         printf(" (No description available)\n");
169         }
170         total_interfaces = i;
171
172         if (i == 0) {
173                 printf
174                     ("\nNo interfaces found! Make sure WinPcap is installed.\n");
175                 goto error_return;
176         }
177
178         printf("Enter the interface number (1-%d):", i);
179         scanf_s("%d", &inum);
180
181         if (inum < 1 || inum > i) {
182                 printf("\nInterface number out of range.\n");
183                 /* Free the device list */
184                 pcap_freealldevs(netif->alldevs);
185                 goto error_return;
186         }
187
188         /* Jump to the selected adapter */
189         for (netif->d = netif->alldevs, i = 0; i < inum - 1;
190              netif->d = netif->d->next, i++) ;
191
192         /* Open the device */
193         if ((netif->pcap_interface = pcap_open_live(netif->d->name,     // name of the device
194                                                     65536,      // portion of the packet to capture
195                                                     // 65536 guarantees that the whole packet will be captured on all the link layers
196                                                     1,  // promiscuous mode
197                                                     timeout_ms, // read timeout in ms
198                                                     netif->errbuf       // error buffer
199              )) == NULL) {
200                 fprintf(stderr,
201                         "\nUnable to open the adapter. %s is not supported by WinPcap\n",
202                         netif->d->name);
203                 /* Free the device list */
204                 pcap_freealldevs(netif->alldevs);
205                 goto error_return;
206         }
207
208         /* lookup ip address */
209         AdapterInfo =
210             (IP_ADAPTER_INFO *) calloc(total_interfaces,
211                                        sizeof(IP_ADAPTER_INFO));
212         AIS = sizeof(IP_ADAPTER_INFO) * total_interfaces;
213         status = GetAdaptersInfo(AdapterInfo, &AIS);
214         if (status != ERROR_SUCCESS) {
215                 fprintf(stderr,
216                         "\nError, GetAdaptersInfo() call in netif_win32_pcap.c failed\n");
217                 free(AdapterInfo);
218                 goto error_return;
219         }
220
221         for (Current = AdapterInfo; Current != NULL; Current = Current->Next) {
222                 if (strstr(netif->d->name, Current->AdapterName) != 0) {
223                         uint32_t my_ip;
224                         ULONG len;
225                         uint8_t tmp[16];
226
227                         my_ip =
228                             inet_addr(Current->IpAddressList.IpAddress.String);
229                         len = sizeof(tmp);
230                         SendARP(my_ip, INADDR_ANY, tmp, &len);
231                         memcpy(netif->mac, &tmp[0], sizeof(netif->mac));
232                 }
233         }
234         free(AdapterInfo);
235         return netif;
236
237  error_return:
238         free(netif);
239         return NULL;
240 }
241
242 int netif_close(struct netif *net_if)
243 {
244         /* At this point, we don't need any more the device list. Free it */
245         pcap_freealldevs(net_if->alldevs);
246         pcap_close(net_if->pcap_interface);
247         free(net_if);
248         return (0);
249 }
250
251 int netif_set_capture_ethertype(struct netif *net_if, uint16_t * ethertype,
252                                 uint32_t count)
253 {
254         struct bpf_program fcode;
255         char ethertype_string[512];
256         char ethertype_single[64];
257         unsigned int i;
258
259         ethertype_string[0] = 0;
260         for (i = 0; i < count; i++) {
261                 sprintf(ethertype_single, "ether proto 0x%04x", ethertype[i]);
262                 strcat(ethertype_string, ethertype_single);
263                 if ((i + 1) < count)
264                         strcat(ethertype_string, " or ");
265         }
266
267         // compile a filter
268         if (pcap_compile(net_if->pcap_interface, &fcode, ethertype_string, 1, 0)
269             < 0) {
270                 fprintf(stderr,
271                         "\nUnable to compile the packet filter. Check the syntax.\n");
272                 /* Free the device list */
273                 pcap_freealldevs(net_if->alldevs);
274                 return -1;
275         }
276         //set the filter
277         if (pcap_setfilter(net_if->pcap_interface, &fcode) < 0) {
278                 fprintf(stderr, "\nError setting the filter.\n");
279                 /* Free the device list */
280                 pcap_freealldevs(net_if->alldevs);
281                 return -1;
282         }
283
284         return (0);
285 }
286
287 int netif_capture_frame(struct netif *net_if, uint8_t ** frame,
288                         uint16_t * length)
289 {
290         struct pcap_pkthdr *header;
291         int error = 0;
292
293         *length = 0;
294         error = pcap_next_ex(net_if->pcap_interface, &header, frame);
295         if (error > 0) {
296                 *length = (uint16_t) header->len;
297                 return (1);
298         } else {
299                 return (NETIF_TIMEOUT);
300         }
301 }
302
303 int netif_send_frame(struct netif *net_if, uint8_t * frame, uint16_t length)
304 {
305         //printf("TX frame: %d bytes\n", length);
306         if (pcap_sendpacket(net_if->pcap_interface, frame, length) != 0) {
307                 fprintf(stderr, "\nError sending the packet: \n",
308                         pcap_geterr(net_if->pcap_interface));
309                 return -1;
310         }
311         return (0);
312 }
313
314 struct netif_thread_data {
315         uint8_t *frame;
316         uint16_t length;
317 };
318
319 DWORD WINAPI netif_thread(LPVOID lpParam)
320 {
321         int status;
322         struct netif_thread_data d;
323
324         while (WaitForSingleObject(sem_kill_wpcap_thread, 0)) {
325                 status = netif_capture_frame(net_if, &d.frame, &d.length);
326                 if (status > 0) {
327                         que_push(que_wpcap, &d);
328                 } else {
329                         if (!SetEvent(pkt_events[pkt_event_wpcap_timeout])) {
330                                 printf
331                                     ("SetEvent pkt_event_wpcap_timeout failed (%d)\n",
332                                      GetLastError());
333                                 return 1;
334                         }
335                 }
336         }
337         return 0;
338 }
339
340 static int clock_monotonic_in_ms_init = 0;
341 static LARGE_INTEGER clock_monotonic_freq;
342
343 unsigned int clock_monotonic_in_ms(void)
344 {
345         LARGE_INTEGER count;
346         QueryPerformanceCounter(&count);
347         if (!clock_monotonic_in_ms_init) {
348                 QueryPerformanceFrequency(&clock_monotonic_freq);
349                 clock_monotonic_in_ms_init = 1;
350         }
351         return (unsigned int)((double)count.QuadPart * 1000.0 /
352                               (double)clock_monotonic_freq.QuadPart);
353 }
354
355 HTIMER mrpd_timer_create(void)
356 {
357         return (struct wtimer *)calloc(1, sizeof(struct wtimer));
358 }
359
360 void mrpd_timer_close(HTIMER t)
361 {
362         if (t)
363                 free(t);
364 }
365
366 int mrpd_timer_start_interval(HTIMER timerfd,
367                               unsigned long value_ms, unsigned long interval_ms)
368 {
369         struct wtimer *t = (struct wtimer *)timerfd;
370         t->running = TRUE;
371         t->elapsed = FALSE;
372         t->count = value_ms;
373         t->interval = interval_ms;
374         t->start_time = clock_monotonic_in_ms();
375         return 0;
376 }
377
378 int mrpd_timer_start(HTIMER timerfd, unsigned long value_ms)
379 {
380         return mrpd_timer_start_interval(timerfd, value_ms, 0);
381 }
382
383 int mrpd_timer_restart(HTIMER timerfd)
384 {
385         struct wtimer *t = (struct wtimer *)timerfd;
386         if (t->interval) {
387                 t->start_time = t->start_time + t->interval;
388                 t->running = TRUE;
389                 t->elapsed = FALSE;
390         }
391         return 0;
392 }
393
394 int mrpd_timer_stop(HTIMER timerfd)
395 {
396         struct wtimer *t = (struct wtimer *)timerfd;
397         t->running = FALSE;
398         t->elapsed = FALSE;
399         return 0;
400 }
401
402 int mrpd_timer_timeout(HTIMER timerfd)
403 {
404         struct wtimer *t = (struct wtimer *)timerfd;
405         if (t->running && !t->elapsed) {
406                 unsigned int elapsed_ms;
407                 unsigned int current_time = clock_monotonic_in_ms();
408                 elapsed_ms = current_time - t->start_time;
409                 if (elapsed_ms > t->count) {
410                         t->elapsed = TRUE;
411                 }
412         }
413         return t->elapsed;
414 }
415
416 int gctimer_start()
417 {
418         /* reclaim memory every 30 minutes */
419         return mrpd_timer_start(gc_timer, 30 * 60 * 1000);
420 }
421
422 int periodictimer_start()
423 {
424         /* periodictimer has expired. (10.7.5.23)
425          * PeriodicTransmission state machine generates periodic events
426          * period is one-per-sec
427          */
428         return mrpd_timer_start_interval(periodic_timer, 1000, 1000);
429 }
430
431 int periodictimer_stop()
432 {
433         /* periodictimer has expired. (10.7.5.23)
434          * PeriodicTransmission state machine generates periodic events
435          * period is one-per-sec
436          */
437         return mrpd_timer_stop(periodic_timer);
438 }
439
440 int mrpd_init_timers(struct mrp_database *mrp_db)
441 {
442         mrp_db->join_timer = mrpd_timer_create();
443         mrp_db->lv_timer = mrpd_timer_create();
444         mrp_db->lva_timer = mrpd_timer_create();
445
446         if (NULL == mrp_db->join_timer)
447                 goto out;
448         if (NULL == mrp_db->lv_timer)
449                 goto out;
450         if (NULL == mrp_db->lva_timer)
451                 goto out;
452         return 0;
453  out:
454         mrpd_timer_close(mrp_db->join_timer);
455         mrpd_timer_close(mrp_db->lv_timer);
456         mrpd_timer_close(mrp_db->lva_timer);
457
458         return -1;
459 }
460
461 int init_timers(void)
462 {
463         /*
464          * primarily whether to schedule the periodic timer as the
465          * rest are self-scheduling as a side-effect of state transitions
466          * of the various attributes
467          */
468
469         periodic_timer = mrpd_timer_create();
470         gc_timer = mrpd_timer_create();
471
472         if (NULL == periodic_timer)
473                 goto out;
474         if (NULL == gc_timer)
475                 goto out;
476
477         gctimer_start();
478
479         if (periodic_enable)
480                 periodictimer_start();
481
482         return 0;
483  out:
484         return -1;
485 }
486
487 //sockaddr
488
489 int process_ctl_msg(char *buf, int buflen, struct sockaddr_in *client)
490 {
491
492         char respbuf[8];
493         /*
494          * Inbound/output commands from/to a client:
495          *
496          * When sent from a client, indicates an operation on the
497          * internal attribute databases. When sent by the daemon to
498          * a client, indicates an event such as a new attribute arrival,
499          * or a leaveall timer to force clients to re-advertise continued
500          * interest in an attribute.
501          *
502          * BYE   Client detaches from daemon
503          *
504          * M+? - JOIN_MT a MAC address or service declaration
505          * M++   JOIN_IN a MAC Address (XXX: MMRP doesn't use 'New' though?)
506          * M-- - LV a MAC address or service declaration
507          * V+? - JOIN_MT a VID (VLAN ID)
508          * V++ - JOIN_IN a VID (VLAN ID)
509          * V-- - LV a VID (VLAN ID)
510          * S+? - JOIN_MT a Stream
511          * S++ - JOIN_IN a Stream
512          * S-- - LV a Stream
513          *
514          * Outbound messages
515          * ERC - error, unrecognized command
516          * ERP - error, unrecognized parameter
517          * ERI - error, internal
518          * OK+ - success
519          *
520          * Registrar Commands
521          *
522          * M?? - query MMRP Registrar MAC Address database
523          * V?? - query MVRP Registrar VID database
524          * S?? - query MSRP Registrar database
525          *
526          * Registrar Responses (to ?? commands)
527          *
528          * MIN - Registered
529          * MMT - Registered, Empty
530          * MLV - Registered, Leaving
531          * MNE - New attribute notification
532          * MJO - JOIN attribute notification
533          * MLV - LEAVE attribute notification
534          * VIN - Registered
535          * VMT - Registered, Empty
536          * VLV - Registered, Leaving
537          * SIN - Registered
538          * SMT - Registered, Empty
539          * SLV - Registered, Leaving
540          *
541          */
542
543         memset(respbuf, 0, sizeof(respbuf));
544
545         if (logging_enable)
546                 printf("CMD:%s from CLNT %d\n", buf, client->sin_port);
547
548         if (buflen < 3) {
549                 printf("buflen = %d!\b", buflen);
550
551                 return -1;
552         }
553
554         switch (buf[0]) {
555         case 'M':
556                 return mmrp_recv_cmd(buf, buflen, client);
557                 break;
558         case 'V':
559                 return mvrp_recv_cmd(buf, buflen, client);
560                 break;
561         case 'S':
562                 return msrp_recv_cmd(buf, buflen, client);
563                 break;
564         case 'B':
565                 mmrp_bye(client);
566                 mvrp_bye(client);
567                 msrp_bye(client);
568                 break;
569         default:
570                 printf("unrecognized command %s\n", buf);
571                 snprintf(respbuf, sizeof(respbuf) - 1, "ERC %s", buf);
572                 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
573                 return -1;
574                 break;
575         }
576
577         return 0;
578 }
579
580 static uint8_t *last_pdu_buffer;
581 static int last_pdu_buffer_size;
582
583 int mrpd_recvmsgbuf(SOCKET sock, char **buf)
584 {
585
586         *buf = (char *)malloc(MAX_FRAME_SIZE);
587         if (NULL == *buf)
588                 return -1;
589
590         memcpy(*buf, last_pdu_buffer, last_pdu_buffer_size);
591         return last_pdu_buffer_size;
592 }
593
594 int mrpd_send_ctl_msg(struct sockaddr_in *client_addr,
595                       char *notify_data, int notify_len)
596 {
597
598         int rc;
599
600         if (INVALID_SOCKET == control_socket)
601                 return 0;
602
603         printf("mrpd_send_ctl_msg :%s\n", notify_data);
604         rc = sendto(control_socket, notify_data, notify_len,
605                     0, (struct sockaddr *)client_addr, sizeof(struct sockaddr));
606         return rc;
607 }
608
609 int mrpd_close_socket(SOCKET sock)
610 {
611         return closesocket(sock);
612 }
613
614 size_t mrpd_send(SOCKET sockfd, const void *buf, size_t len, int flags)
615 {
616         if (pcap_sendpacket(net_if->pcap_interface, buf, len) != 0) {
617                 fprintf(stderr, "\nError sending the packet: \n",
618                         pcap_geterr(net_if->pcap_interface));
619                 return -1;
620         }
621         return len;
622 }
623
624 int mrpd_init_protocol_socket(uint16_t etype, SOCKET * sock,
625                               unsigned char *multicast_addr)
626 {
627         *sock = 0x1234;
628         return 0;
629 }
630
631 int init_local_ctl(void)
632 {
633         struct sockaddr_in addr;
634         SOCKET sock_fd = INVALID_SOCKET;
635         int rc;
636         u_long iMode = 1;
637         DWORD iResult;
638         int timeout = 100;      // ms
639
640         sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
641         if (sock_fd == INVALID_SOCKET)
642                 goto out;
643
644         iResult = setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO,
645                              (void *)&timeout, sizeof(timeout));
646         if (iResult != NO_ERROR)
647                 goto out;
648         iResult = setsockopt(sock_fd, SOL_SOCKET, SO_SNDTIMEO,
649                              (void *)&timeout, sizeof(timeout));
650         if (iResult != NO_ERROR)
651                 goto out;
652
653         memset(&addr, 0, sizeof(addr));
654         addr.sin_family = AF_INET;
655         addr.sin_port = htons(mrpd_port);
656         addr.sin_addr.s_addr = inet_addr("127.0.0.1");
657
658         rc = bind(sock_fd, (struct sockaddr *)&addr, sizeof(addr));
659
660         if (rc == SOCKET_ERROR)
661                 goto out;
662
663         control_socket = sock_fd;
664
665         return 0;
666  out:
667         if (sock_fd != INVALID_SOCKET)
668                 closesocket(sock_fd);
669
670         return -1;
671 }
672
673 struct ctl_thread_params {
674         char *msgbuf;
675         struct sockaddr client_addr;
676         int bytes;
677 };
678
679 DWORD WINAPI ctl_thread(LPVOID lpParam)
680 {
681         struct ctl_thread_params s;
682         int client_len;
683
684         while (WaitForSingleObject(sem_kill_localhost_thread, 0)) {
685                 client_len = sizeof(struct sockaddr);
686                 s.msgbuf = (char *)malloc(MAX_MRPD_CMDSZ);
687                 s.bytes =
688                     recvfrom(control_socket, s.msgbuf, MAX_MRPD_CMDSZ, 0,
689                              &s.client_addr, &client_len);
690                 if (s.bytes > 0) {
691                         que_push(que_localhost, &s);
692                 } else {
693                         free(s.msgbuf);
694                         if (!SetEvent(pkt_events[pkt_event_localhost_timeout])) {
695                                 printf
696                                     ("SetEvent pkt_event_localhost_timeout failed (%d)\n",
697                                      GetLastError());
698                                 return 1;
699                         }
700                 }
701         }
702         return 0;
703 }
704
705 int mrpd_reclaim()
706 {
707
708         /*
709          * if the local applications have neither registered interest
710          * by joining, and the remote node has quit advertising the attribute
711          * and allowing it to go into the MT state, delete the attribute 
712          */
713
714         mmrp_reclaim();
715         mvrp_reclaim();
716         msrp_reclaim();
717
718         gctimer_start();
719
720         return 0;
721
722 }
723
724 HANDLE kill_packet_capture;
725
726 void process_events(void)
727 {
728         HANDLE hThread1, hThread2;
729         DWORD dwThreadID1, dwThreadID2;
730         uint16_t length = 0;
731         uint8_t *payload;
732         uint16_t protocol;
733         uint8_t *proto;
734         struct avb_avtpdu *avtpdu = NULL;
735         uint64_t src_mac_address = 0;
736         struct ctl_thread_params localhost_pkt;
737         struct netif_thread_data wpcap_pkt;
738         int i;
739
740         timer_check_tick = mrpd_timer_create();
741         mrpd_timer_start_interval(timer_check_tick, 100, 100);
742
743         que_wpcap = que_new(256, sizeof(struct netif_thread_data));
744         que_localhost = que_new(256, sizeof(struct ctl_thread_params));
745
746         sem_kill_wpcap_thread = CreateSemaphore(NULL, 0, 32767, NULL);
747         sem_kill_localhost_thread = CreateSemaphore(NULL, 0, 32767, NULL);
748         for (i = pkt_event_wpcap_timeout; i <= loop_time_tick; i++) {
749                 pkt_events[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
750                 if (pkt_events[i] == NULL) {
751                         fprintf(stderr, "CreateEvent error: %d\n",
752                                 GetLastError());
753                         ExitProcess(0);
754                 }
755         }
756         pkt_events[pkt_event_wpcap] = que_data_available_object(que_wpcap);
757         pkt_events[pkt_event_localhost] =
758             que_data_available_object(que_localhost);
759
760         // Create threads
761         hThread1 = CreateThread(NULL,   // default security attributes
762                                 0,      // default stack size
763                                 (LPTHREAD_START_ROUTINE) netif_thread, NULL,    // no thread function arguments
764                                 0,      // default creation flags
765                                 &dwThreadID1);  // receive thread identifier
766
767         if (hThread1 == NULL) {
768                 fprintf(stderr, "CreateThread error: %d\n", GetLastError());
769                 ExitProcess(0);
770         }
771
772         hThread2 = CreateThread(NULL,   // default security attributes
773                                 0,      // default stack size
774                                 (LPTHREAD_START_ROUTINE) ctl_thread, NULL,      // no thread function arguments
775                                 0,      // default creation flags
776                                 &dwThreadID2);  // receive thread identifier
777
778         if (hThread1 == NULL) {
779                 fprintf(stderr, "CreateThread error: %d\n", GetLastError());
780                 ExitProcess(0);
781         }
782
783         while (1) {
784                 DWORD dwEvent =
785                     WaitForMultipleObjects(sizeof(pkt_events) / sizeof(HANDLE),
786                                            pkt_events,
787                                            FALSE,
788                                            100);        /* 100ms wait */
789
790                 /* special exit case */
791                 if (WAIT_OBJECT_0 + app_event_kill_all == dwEvent)
792                         break;
793
794                 switch (dwEvent) {
795                 case WAIT_TIMEOUT:
796                 case WAIT_OBJECT_0 + loop_time_tick:
797                         /* timeout - run protocols */
798                         if (mrpd_timer_timeout(MMRP_db->mrp_db.lva_timer))
799                                 mmrp_event(MRP_EVENT_LVATIMER, NULL);
800                         if (mrpd_timer_timeout(MMRP_db->mrp_db.lv_timer))
801                                 mmrp_event(MRP_EVENT_LVTIMER, NULL);
802                         if (mrpd_timer_timeout(MMRP_db->mrp_db.join_timer))
803                                 mmrp_event(MRP_EVENT_TX, NULL);
804
805                         if (mrpd_timer_timeout(MVRP_db->mrp_db.lva_timer))
806                                 mvrp_event(MRP_EVENT_LVATIMER, NULL);
807                         if (mrpd_timer_timeout(MVRP_db->mrp_db.lv_timer))
808                                 mvrp_event(MRP_EVENT_LVTIMER, NULL);
809                         if (mrpd_timer_timeout(MVRP_db->mrp_db.join_timer))
810                                 mvrp_event(MRP_EVENT_TX, NULL);
811
812                         if (mrpd_timer_timeout(MSRP_db->mrp_db.lva_timer))
813                                 msrp_event(MRP_EVENT_LVATIMER, NULL);
814                         if (mrpd_timer_timeout(MSRP_db->mrp_db.lv_timer))
815                                 msrp_event(MRP_EVENT_LVTIMER, NULL);
816                         if (mrpd_timer_timeout(MSRP_db->mrp_db.join_timer))
817                                 msrp_event(MRP_EVENT_TX, NULL);
818
819                         if (mrpd_timer_timeout(periodic_timer)) {
820                                 //printf("mrpd_timer_timeout(periodic_timer)\n");
821                                 mmrp_event(MRP_EVENT_PERIODIC, NULL);
822                                 mvrp_event(MRP_EVENT_PERIODIC, NULL);
823                                 msrp_event(MRP_EVENT_PERIODIC, NULL);
824                                 mrpd_timer_restart(periodic_timer);
825                         }
826                         if (mrpd_timer_timeout(gc_timer)) {
827                                 mrpd_reclaim();
828                         }
829                         mrpd_timer_restart(timer_check_tick);
830                         break;
831
832                 case WAIT_OBJECT_0 + pkt_event_wpcap:
833                         printf("pkt_event_wpcap\n");
834                         que_pop_nowait(que_wpcap, &wpcap_pkt);
835                         proto = &wpcap_pkt.frame[12];
836                         protocol =
837                             (uint16_t) proto[0] << 8 | (uint16_t) proto[1];
838                         payload = proto + 2;
839
840                         last_pdu_buffer = wpcap_pkt.frame;
841                         last_pdu_buffer_size = wpcap_pkt.length;
842
843                         switch (protocol) {
844                         case MVRP_ETYPE:
845                                 mvrp_recv_msg();
846                                 break;
847
848                         case MMRP_ETYPE:
849                                 mmrp_recv_msg();
850                                 break;
851
852                         case MSRP_ETYPE:
853                                 msrp_recv_msg();
854                                 break;
855                         }
856                         if (mrpd_timer_timeout(&timer_check_tick)) {
857                                 if (!SetEvent(pkt_events[loop_time_tick])) {
858                                         printf
859                                             ("SetEvent loop_time_tick failed (%d)\n",
860                                              GetLastError());
861                                         exit(-1);
862                                 }
863                         }
864                         break;
865
866                 case WAIT_OBJECT_0 + pkt_event_wpcap_timeout:
867                         //printf("pkt_event_wpcap_timeout\n");
868                         break;
869
870                 case WAIT_OBJECT_0 + pkt_event_localhost:
871                         printf("pkt_event_localhost\n");
872                         que_pop_nowait(que_localhost, &localhost_pkt);
873                         process_ctl_msg(localhost_pkt.msgbuf,
874                                         localhost_pkt.bytes,
875                                         (struct sockaddr_in *)
876                                         &localhost_pkt.client_addr);
877                         if (mrpd_timer_timeout(&timer_check_tick)) {
878                                 if (!SetEvent(pkt_events[loop_time_tick])) {
879                                         printf
880                                             ("SetEvent loop_time_tick failed (%d)\n",
881                                              GetLastError());
882                                         exit(-1);
883                                 }
884                         }
885                         break;
886
887                 case WAIT_OBJECT_0 + pkt_event_localhost_timeout:
888                         //printf("pkt_event_localhost_timeout\n");
889                         break;
890
891                 default:
892                         printf("Unknown event %d\n", dwEvent);
893                 }
894         }
895 }
896
897 int main(int argc, char *argv[])
898 {
899         uint16_t ether_types[4];
900         WSADATA wsa_data;
901         int rc;
902
903         mrpd_port = MRPD_PORT_DEFAULT;
904         mmrp_enable = 1;
905         mvrp_enable = 1;
906         msrp_enable = 1;
907         periodic_enable = 1;
908         logging_enable = 1;
909
910         WSAStartup(MAKEWORD(1, 1), &wsa_data);
911
912         /* open our network interface and set the capture ethertype to MRP types */
913         net_if = netif_open(TIME_PERIOD_100_MILLISECONDS);      // time out is 100ms
914         if (!net_if) {
915                 fprintf(stderr, "ERROR - opening network interface\n");
916                 exit(-1);
917         }
918
919         ether_types[0] = MVRP_ETYPE;
920         ether_types[1] = MMRP_ETYPE;
921         ether_types[2] = MSRP_ETYPE;
922         if (netif_set_capture_ethertype(net_if, ether_types, 3)) {
923                 fprintf(stderr, "ERROR - setting netif capture ethertype\n");
924                 exit(-1);
925         }
926
927         rc = mrp_init();
928         if (rc)
929                 goto out;
930
931         rc = init_local_ctl();
932         if (rc)
933                 goto out;
934
935         rc = mmrp_init(mmrp_enable);
936         if (rc)
937                 goto out;
938
939         rc = mvrp_init(mvrp_enable);
940         if (rc)
941                 goto out;
942
943         rc = msrp_init(msrp_enable);
944         if (rc)
945                 goto out;
946
947         rc = init_timers();
948         if (rc)
949                 goto out;
950
951         process_events();
952  out:
953         if (rc)
954                 printf("Error starting. Run as sudo?\n");
955
956         WSACleanup();
957         return rc;
958
959 }