1 /******************************************************************************
3 Copyright (c) 2012, Intel Corporation
4 Copyright (c) 2012, AudioScience, Inc
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
10 1. Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
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.
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.
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.
33 ******************************************************************************/
35 * Main code for Windows implementation of MRP/MMRP/MVRP/MSRP
53 #define TIME_PERIOD_100_MILLISECONDS 100
54 #define NETIF_TIMEOUT (-2)
61 unsigned int interval;
62 unsigned int start_time;
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
84 pkt_event_wpcap_timeout,
85 pkt_event_localhost_timeout,
90 /* global mgmt parameters */
98 HANDLE sem_kill_wpcap_thread;
99 HANDLE sem_kill_localhost_thread;
100 struct que_def *que_wpcap;
101 struct que_def *que_localhost;
103 //char *net_interface;
106 /* state machine controls */
110 /* if registration is FIXED or FORBIDDEN
111 * updates from MRP are discarded, and
112 * only IN and JOININ messages are sent
117 /* if participant role is 'SILENT' (or non-participant)
118 * applicant doesn't send any messages - configured per-attribute
121 #define VERSION_STR "0.0"
123 static const char *version_str =
124 "mrpw v" VERSION_STR "\n" "Copyright (c) 2012, AudioScience Inc\n";
126 unsigned char STATION_ADDR[] = { 0x00, 0x88, 0x77, 0x66, 0x55, 0x44 };
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;
135 HTIMER periodic_timer;
137 HTIMER timer_check_tick;
139 extern struct mmrp_database *MMRP_db;
140 extern struct mvrp_database *MVRP_db;
141 extern struct msrp_database *MSRP_db;
143 struct netif *netif_open(int timeout_ms)
146 int i = 0, total_interfaces = 0;
148 IP_ADAPTER_INFO *AdapterInfo;
149 IP_ADAPTER_INFO *Current;
153 netif = (struct netif *)calloc(1, sizeof(struct netif));
155 /* Retrieve the device list on the local machine */
156 if (pcap_findalldevs(&netif->alldevs, netif->errbuf) == -1) {
157 printf("Error finding interfaces\n");
162 for (netif->d = netif->alldevs; netif->d; netif->d = netif->d->next) {
163 /*printf("%d. %s", ++i, d->name); */
165 if (netif->d->description)
166 printf(" (%-70s)\n", netif->d->description);
168 printf(" (No description available)\n");
170 total_interfaces = i;
174 ("\nNo interfaces found! Make sure WinPcap is installed.\n");
178 printf("Enter the interface number (1-%d):", i);
179 scanf_s("%d", &inum);
181 if (inum < 1 || inum > i) {
182 printf("\nInterface number out of range.\n");
183 /* Free the device list */
184 pcap_freealldevs(netif->alldevs);
188 /* Jump to the selected adapter */
189 for (netif->d = netif->alldevs, i = 0; i < inum - 1;
190 netif->d = netif->d->next, i++) ;
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
201 "\nUnable to open the adapter. %s is not supported by WinPcap\n",
203 /* Free the device list */
204 pcap_freealldevs(netif->alldevs);
208 /* lookup ip address */
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) {
216 "\nError, GetAdaptersInfo() call in netif_win32_pcap.c failed\n");
221 for (Current = AdapterInfo; Current != NULL; Current = Current->Next) {
222 if (strstr(netif->d->name, Current->AdapterName) != 0) {
228 inet_addr(Current->IpAddressList.IpAddress.String);
230 SendARP(my_ip, INADDR_ANY, tmp, &len);
231 memcpy(netif->mac, &tmp[0], sizeof(netif->mac));
242 int netif_close(struct netif *net_if)
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);
251 int netif_set_capture_ethertype(struct netif *net_if, uint16_t * ethertype,
254 struct bpf_program fcode;
255 char ethertype_string[512];
256 char ethertype_single[64];
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);
264 strcat(ethertype_string, " or ");
268 if (pcap_compile(net_if->pcap_interface, &fcode, ethertype_string, 1, 0)
271 "\nUnable to compile the packet filter. Check the syntax.\n");
272 /* Free the device list */
273 pcap_freealldevs(net_if->alldevs);
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);
287 int netif_capture_frame(struct netif *net_if, uint8_t ** frame,
290 struct pcap_pkthdr *header;
294 error = pcap_next_ex(net_if->pcap_interface, &header, frame);
296 *length = (uint16_t) header->len;
299 return (NETIF_TIMEOUT);
303 int netif_send_frame(struct netif *net_if, uint8_t * frame, uint16_t length)
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));
314 struct netif_thread_data {
319 DWORD WINAPI netif_thread(LPVOID lpParam)
322 struct netif_thread_data d;
324 while (WaitForSingleObject(sem_kill_wpcap_thread, 0)) {
325 status = netif_capture_frame(net_if, &d.frame, &d.length);
327 que_push(que_wpcap, &d);
329 if (!SetEvent(pkt_events[pkt_event_wpcap_timeout])) {
331 ("SetEvent pkt_event_wpcap_timeout failed (%d)\n",
340 static int clock_monotonic_in_ms_init = 0;
341 static LARGE_INTEGER clock_monotonic_freq;
343 unsigned int clock_monotonic_in_ms(void)
346 QueryPerformanceCounter(&count);
347 if (!clock_monotonic_in_ms_init) {
348 QueryPerformanceFrequency(&clock_monotonic_freq);
349 clock_monotonic_in_ms_init = 1;
351 return (unsigned int)((double)count.QuadPart * 1000.0 /
352 (double)clock_monotonic_freq.QuadPart);
355 HTIMER mrpd_timer_create(void)
357 return (struct wtimer *)calloc(1, sizeof(struct wtimer));
360 void mrpd_timer_close(HTIMER t)
366 int mrpd_timer_start_interval(HTIMER timerfd,
367 unsigned long value_ms, unsigned long interval_ms)
369 struct wtimer *t = (struct wtimer *)timerfd;
373 t->interval = interval_ms;
374 t->start_time = clock_monotonic_in_ms();
378 int mrpd_timer_start(HTIMER timerfd, unsigned long value_ms)
380 return mrpd_timer_start_interval(timerfd, value_ms, 0);
383 int mrpd_timer_restart(HTIMER timerfd)
385 struct wtimer *t = (struct wtimer *)timerfd;
387 t->start_time = t->start_time + t->interval;
394 int mrpd_timer_stop(HTIMER timerfd)
396 struct wtimer *t = (struct wtimer *)timerfd;
402 int mrpd_timer_timeout(HTIMER timerfd)
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) {
418 /* reclaim memory every 30 minutes */
419 return mrpd_timer_start(gc_timer, 30 * 60 * 1000);
422 int periodictimer_start()
424 /* periodictimer has expired. (10.7.5.23)
425 * PeriodicTransmission state machine generates periodic events
426 * period is one-per-sec
428 return mrpd_timer_start_interval(periodic_timer, 1000, 1000);
431 int periodictimer_stop()
433 /* periodictimer has expired. (10.7.5.23)
434 * PeriodicTransmission state machine generates periodic events
435 * period is one-per-sec
437 return mrpd_timer_stop(periodic_timer);
440 int mrpd_init_timers(struct mrp_database *mrp_db)
442 mrp_db->join_timer = mrpd_timer_create();
443 mrp_db->lv_timer = mrpd_timer_create();
444 mrp_db->lva_timer = mrpd_timer_create();
446 if (NULL == mrp_db->join_timer)
448 if (NULL == mrp_db->lv_timer)
450 if (NULL == mrp_db->lva_timer)
454 mrpd_timer_close(mrp_db->join_timer);
455 mrpd_timer_close(mrp_db->lv_timer);
456 mrpd_timer_close(mrp_db->lva_timer);
461 int init_timers(void)
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
469 periodic_timer = mrpd_timer_create();
470 gc_timer = mrpd_timer_create();
472 if (NULL == periodic_timer)
474 if (NULL == gc_timer)
480 periodictimer_start();
489 int process_ctl_msg(char *buf, int buflen, struct sockaddr_in *client)
494 * Inbound/output commands from/to a client:
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.
502 * BYE Client detaches from daemon
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
515 * ERC - error, unrecognized command
516 * ERP - error, unrecognized parameter
517 * ERI - error, internal
522 * M?? - query MMRP Registrar MAC Address database
523 * V?? - query MVRP Registrar VID database
524 * S?? - query MSRP Registrar database
526 * Registrar Responses (to ?? commands)
529 * MMT - Registered, Empty
530 * MLV - Registered, Leaving
531 * MNE - New attribute notification
532 * MJO - JOIN attribute notification
533 * MLV - LEAVE attribute notification
535 * VMT - Registered, Empty
536 * VLV - Registered, Leaving
538 * SMT - Registered, Empty
539 * SLV - Registered, Leaving
543 memset(respbuf, 0, sizeof(respbuf));
546 printf("CMD:%s from CLNT %d\n", buf, client->sin_port);
549 printf("buflen = %d!\b", buflen);
556 return mmrp_recv_cmd(buf, buflen, client);
559 return mvrp_recv_cmd(buf, buflen, client);
562 return msrp_recv_cmd(buf, buflen, client);
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));
580 static uint8_t *last_pdu_buffer;
581 static int last_pdu_buffer_size;
583 int mrpd_recvmsgbuf(SOCKET sock, char **buf)
586 *buf = (char *)malloc(MAX_FRAME_SIZE);
590 memcpy(*buf, last_pdu_buffer, last_pdu_buffer_size);
591 return last_pdu_buffer_size;
594 int mrpd_send_ctl_msg(struct sockaddr_in *client_addr,
595 char *notify_data, int notify_len)
600 if (INVALID_SOCKET == control_socket)
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));
609 int mrpd_close_socket(SOCKET sock)
611 return closesocket(sock);
614 size_t mrpd_send(SOCKET sockfd, const void *buf, size_t len, int flags)
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));
624 int mrpd_init_protocol_socket(uint16_t etype, SOCKET * sock,
625 unsigned char *multicast_addr)
631 int init_local_ctl(void)
633 struct sockaddr_in addr;
634 SOCKET sock_fd = INVALID_SOCKET;
638 int timeout = 100; // ms
640 sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
641 if (sock_fd == INVALID_SOCKET)
644 iResult = setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO,
645 (void *)&timeout, sizeof(timeout));
646 if (iResult != NO_ERROR)
648 iResult = setsockopt(sock_fd, SOL_SOCKET, SO_SNDTIMEO,
649 (void *)&timeout, sizeof(timeout));
650 if (iResult != NO_ERROR)
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");
658 rc = bind(sock_fd, (struct sockaddr *)&addr, sizeof(addr));
660 if (rc == SOCKET_ERROR)
663 control_socket = sock_fd;
667 if (sock_fd != INVALID_SOCKET)
668 closesocket(sock_fd);
673 struct ctl_thread_params {
675 struct sockaddr client_addr;
679 DWORD WINAPI ctl_thread(LPVOID lpParam)
681 struct ctl_thread_params s;
684 while (WaitForSingleObject(sem_kill_localhost_thread, 0)) {
685 client_len = sizeof(struct sockaddr);
686 s.msgbuf = (char *)malloc(MAX_MRPD_CMDSZ);
688 recvfrom(control_socket, s.msgbuf, MAX_MRPD_CMDSZ, 0,
689 &s.client_addr, &client_len);
691 que_push(que_localhost, &s);
694 if (!SetEvent(pkt_events[pkt_event_localhost_timeout])) {
696 ("SetEvent pkt_event_localhost_timeout failed (%d)\n",
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
724 HANDLE kill_packet_capture;
726 void process_events(void)
728 HANDLE hThread1, hThread2;
729 DWORD dwThreadID1, dwThreadID2;
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;
740 timer_check_tick = mrpd_timer_create();
741 mrpd_timer_start_interval(timer_check_tick, 100, 100);
743 que_wpcap = que_new(256, sizeof(struct netif_thread_data));
744 que_localhost = que_new(256, sizeof(struct ctl_thread_params));
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",
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);
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
767 if (hThread1 == NULL) {
768 fprintf(stderr, "CreateThread error: %d\n", GetLastError());
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
778 if (hThread1 == NULL) {
779 fprintf(stderr, "CreateThread error: %d\n", GetLastError());
785 WaitForMultipleObjects(sizeof(pkt_events) / sizeof(HANDLE),
788 100); /* 100ms wait */
790 /* special exit case */
791 if (WAIT_OBJECT_0 + app_event_kill_all == dwEvent)
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);
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);
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);
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);
826 if (mrpd_timer_timeout(gc_timer)) {
829 mrpd_timer_restart(timer_check_tick);
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];
837 (uint16_t) proto[0] << 8 | (uint16_t) proto[1];
840 last_pdu_buffer = wpcap_pkt.frame;
841 last_pdu_buffer_size = wpcap_pkt.length;
856 if (mrpd_timer_timeout(&timer_check_tick)) {
857 if (!SetEvent(pkt_events[loop_time_tick])) {
859 ("SetEvent loop_time_tick failed (%d)\n",
866 case WAIT_OBJECT_0 + pkt_event_wpcap_timeout:
867 //printf("pkt_event_wpcap_timeout\n");
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,
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])) {
880 ("SetEvent loop_time_tick failed (%d)\n",
887 case WAIT_OBJECT_0 + pkt_event_localhost_timeout:
888 //printf("pkt_event_localhost_timeout\n");
892 printf("Unknown event %d\n", dwEvent);
897 int main(int argc, char *argv[])
899 uint16_t ether_types[4];
903 mrpd_port = MRPD_PORT_DEFAULT;
910 WSAStartup(MAKEWORD(1, 1), &wsa_data);
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
915 fprintf(stderr, "ERROR - opening network interface\n");
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");
931 rc = init_local_ctl();
935 rc = mmrp_init(mmrp_enable);
939 rc = mvrp_init(mvrp_enable);
943 rc = msrp_init(msrp_enable);
954 printf("Error starting. Run as sudo?\n");