1/*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License as
4 * published by the Free Software Foundation; either version 2 of
5 * the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
15 * MA 02111-1307 USA
16 */
17#include <stdlib.h>
18#include <unistd.h>
19#include <stdio.h>
20#include <string.h>
21#include <sys/socket.h>
22#include <sys/types.h>
23#include <netinet/in.h>
24#include <net/if.h>
25#include <arpa/inet.h>
26#include <netdb.h>
27#include <signal.h>
28#include <bcmnvram.h>
29
30#define MAXSENDLEN 256
31#define PORT_DEVICEINFO 7031
32#define PORT_CLIENTMSG 7032
33#define LAN_DEV "br0"
34
35int sockfd_broadcast;
36int sockfd_unicast;
37
38void sendInfo(char *buf, int len, int port)
39{
40	struct sockaddr_in clntaddr;
41	int sendbytes;
42
43	clntaddr.sin_family = AF_INET;
44	clntaddr.sin_port = htons(port);
45	clntaddr.sin_addr.s_addr = inet_addr("255.255.255.255");
46
47	if (setsockopt(sockfd_broadcast, SOL_SOCKET, SO_BINDTODEVICE, LAN_DEV, IFNAMSIZ) != 0)
48	{
49		fprintf(stderr, "setsockopt error: %s\n", LAN_DEV);
50		perror("setsockopt set:");
51	}
52
53	sendbytes = sendto(sockfd_broadcast, buf, len, 0, (struct sockaddr *)&clntaddr, sizeof(clntaddr));
54
55	if (setsockopt(sockfd_broadcast, SOL_SOCKET, SO_BINDTODEVICE, "", IFNAMSIZ) != 0)
56	{
57		fprintf(stderr, "setsockopt error: %s\n", "");
58		perror("setsockopt reset:");
59	}
60}
61
62void catch_sig(int sig)
63{
64	int sendbytes;
65	char sendbuffer[MAXSENDLEN + 1];
66
67	if (sig == SIGUSR1)
68	{
69		memset(sendbuffer, 0, MAXSENDLEN + 1);
70		// response format: "USB device name","current status of the device","IP of cccupied user"
71		if (!nvram_safe_get("u2ec_device"))
72			sprintf(sendbuffer, "\"%s\",\"%s\"", "", "");
73		else if (nvram_invmatch("u2ec_busyip", ""))
74			sprintf(sendbuffer, "\"%s\",\"%s\",\"%s\"", nvram_safe_get("u2ec_device"), "Busy", nvram_safe_get("u2ec_busyip"));
75		else
76			sprintf(sendbuffer, "\"%s\",\"%s\"", nvram_safe_get("u2ec_device"), "Idle");
77		sendbytes = (strlen(sendbuffer) > MAXSENDLEN) ? MAXSENDLEN : strlen(sendbuffer);
78
79		sendInfo(sendbuffer, sendbytes, PORT_DEVICEINFO);
80	}
81	else if (sig == SIGUSR2)
82	{
83		memset(sendbuffer, 0, MAXSENDLEN + 1);
84		strcpy(sendbuffer, nvram_safe_get("u2ec_msg_broadcast"));
85		sendbytes = (strlen(sendbuffer) > MAXSENDLEN) ? MAXSENDLEN : strlen(sendbuffer);
86
87		sendInfo(sendbuffer, sendbytes, PORT_CLIENTMSG);
88	}
89	else if (sig == SIGTSTP)
90	{
91		struct sockaddr_in clntaddr;
92
93		clntaddr.sin_family = AF_INET;
94		clntaddr.sin_port = htons(PORT_CLIENTMSG);
95		clntaddr.sin_addr.s_addr = inet_addr(nvram_safe_get("u2ec_clntip_unicast"));
96
97		memset(sendbuffer, 0, MAXSENDLEN + 1);
98		sprintf(sendbuffer, nvram_safe_get("u2ec_msg_unicast"));
99		sendbytes = (strlen(sendbuffer) > MAXSENDLEN) ? MAXSENDLEN : strlen(sendbuffer);
100
101		sendto(sockfd_unicast, sendbuffer, sendbytes, 0, (struct sockaddr *)&clntaddr, sizeof(clntaddr));
102	}
103}
104
105int usdsvr_broadcast()
106{
107	FILE *fp;
108
109	/* write pid */
110	if ((fp=fopen("/var/run/usdsvr_broadcast.pid", "w"))!=NULL)
111	{
112		fprintf(fp, "%d", getpid());
113		fclose(fp);
114	}
115
116	int broadcast = 1;
117	struct sockaddr_in servaddr;
118
119	bzero((char *)&servaddr , sizeof(servaddr));
120	servaddr.sin_family		= AF_INET;
121	servaddr.sin_addr.s_addr	= htonl(INADDR_ANY);
122	servaddr.sin_port		= htons(PORT_DEVICEINFO);
123
124	if ((sockfd_broadcast = socket(AF_INET, SOCK_DGRAM,0)) < 0 )
125	{
126		perror("socket: SOCK_DGRAM");
127		exit(0);
128	}
129
130	if (setsockopt(sockfd_broadcast , SOL_SOCKET , SO_BROADCAST ,(char *)&broadcast,sizeof(broadcast)) == -1)
131	{
132		perror("setsockopt: SO_BROADCAST");
133		exit(0);
134	}
135
136	if (bind(sockfd_broadcast,(struct sockaddr *)&servaddr , sizeof(servaddr)) < 0 )
137	{
138		perror("bind: sockfd_broadcast");
139		exit(0);
140    	}
141
142	signal(SIGUSR1, catch_sig);
143	signal(SIGUSR2, catch_sig);
144
145	while (1)
146	{
147		pause();
148	}
149
150	return 0;
151}
152
153int usdsvr_unicast()
154{
155	FILE *fp;
156
157	/* write pid */
158	if ((fp=fopen("/var/run/usdsvr_unicast.pid", "w"))!=NULL)
159	{
160		fprintf(fp, "%d", getpid());
161		fclose(fp);
162	}
163
164	struct sockaddr_in servaddr;
165
166	bzero((char *)&servaddr , sizeof(servaddr));
167	servaddr.sin_family		= AF_INET;
168	servaddr.sin_addr.s_addr	= htonl(INADDR_ANY);
169	servaddr.sin_port		= htons(PORT_CLIENTMSG);
170
171	if ((sockfd_unicast = socket(AF_INET, SOCK_DGRAM,0)) < 0 )
172	{
173		perror("socket: SOCK_DGRAM");
174		exit(0);
175	}
176
177	if (bind(sockfd_unicast,(struct sockaddr *)&servaddr , sizeof(servaddr)) < 0 )
178	{
179		perror("bind: sockfd_unicast");
180		exit(0);
181    	}
182
183	signal(SIGTSTP, catch_sig);
184
185	while (1)
186	{
187		pause();
188	}
189
190	return 0;
191}
192