source: trunk/module-radegast.c@ 1672

Last change on this file since 1672 was 1672, checked in by merek, 11 years ago

Replace bzero with memset, as bzero is deprecated on the most oses and not portable

File size: 7.1 KB
Line 
1#include "globals.h"
2
3static int radegast_send(uchar *buf)
4{
5 int l=buf[1]+2;
6 return(send(pfd, buf, l, 0));
7}
8
9static int radegast_recv(uchar *buf, int l)
10{
11 int n;
12 if (!pfd) return(-1);
13 if (is_server) { // server code
14 if ((n=recv(pfd, buf, l, 0))>0)
15 client[cs_idx].last=time((time_t *) 0);
16 } else { // client code
17 if ((n=recv(pfd, buf, l, 0))>0) {
18 cs_ddump(buf, n, "radegast: received %d bytes from %s", n, remote_txt());
19 client[cs_idx].last = time((time_t *) 0);
20
21 if (buf[0] == 2) { // dcw received
22 if (buf[3] != 0x10) { // dcw ok
23 cs_log("radegast: no dcw");
24 n = -1;
25 }
26 }
27 }
28 }
29 return(n);
30}
31
32static int radegast_recv_chk(uchar *dcw, int *rc, uchar *buf)
33{
34 if ((buf[0] == 2) && (buf[1] == 0x12)) {
35 memcpy(dcw, buf+4, 16);
36 cs_debug("radegast: recv chk - %s", cs_hexdump(0, dcw, 16));
37 *rc = 1;
38 return(reader[ridx].msg_idx);
39 }
40
41 return (-1);
42}
43
44static void radegast_auth_client(in_addr_t ip)
45{
46 int ok;
47 struct s_auth *account;
48 struct s_ip *p_ip;
49
50 for (ok=0, p_ip=cfg->rad_allowed; (p_ip) && (!ok); p_ip=p_ip->next)
51 ok=((ip>=p_ip->ip[0]) && (ip<=p_ip->ip[1]));
52
53 if (!ok)
54 {
55 cs_auth_client((struct s_auth *)0, NULL);
56 cs_exit(0);
57 }
58
59 for (ok=0, account=cfg->account; (cfg->rad_usr[0]) && (account) && (!ok); account=account->next)
60 {
61 ok=(!strcmp(cfg->rad_usr, account->usr));
62 if (ok && cs_auth_client(account, NULL))
63 cs_exit(0);
64 }
65
66 if (!ok)
67 cs_auth_client((struct s_auth *)(-1), NULL);
68}
69
70static int get_request(uchar *buf)
71{
72 int n, rc=0;
73 if ((n=process_input(buf, 2, cfg->cmaxidle))==2)
74 {
75 if ((n=process_input(buf+2, buf[1], 0))>=0)
76 n+=2;
77 if (n-2==buf[1])
78 rc=n;
79 else
80 cs_log("WARNING: protocol error (garbage)");
81 }
82 if (n>0)
83 cs_ddump(buf, n, "received %d bytes from client", n);
84 return(rc);
85}
86
87static void radegast_send_dcw(ECM_REQUEST *er)
88{
89 mbuf[0]=0x02; // DCW
90 if (er->rc<4)
91 {
92 mbuf[1]=0x12; // len (overall)
93 mbuf[2]=0x05; // ACCESS
94 mbuf[3]=0x10; // len
95 memcpy(mbuf+4, er->cw, 16);
96 }
97 else
98 {
99 mbuf[1]=0x02; // len (overall)
100 mbuf[2]=0x04; // NO ACCESS
101 mbuf[3]=0x00; // len
102 }
103 radegast_send(mbuf);
104}
105
106static void radegast_process_ecm(uchar *buf, int l)
107{
108 int i, n, sl;
109 ECM_REQUEST *er;
110
111 if (!(er=get_ecmtask()))
112 return;
113 for (i=0; i<l; i+=(sl+2))
114 {
115 sl=buf[i+1];
116 switch(buf[i])
117 {
118 case 2: // CAID (upper byte only, oldstyle)
119 er->caid=buf[i+2]<<8;
120 break;
121 case 10: // CAID
122 er->caid=b2i(2, buf+i+2);
123 break;
124 case 3: // ECM DATA
125 er->l=sl;
126 memcpy(er->ecm, buf+i+2, er->l);
127 break;
128 case 6: // PROVID (ASCII)
129 n=(sl>6) ? 3 : (sl>>1);
130 er->prid=cs_atoi((char *) buf+i+2+sl-(n<<1), n, 0);
131 break;
132 case 7: // KEYNR (ASCII), not needed
133 break;
134 case 8: // ECM PROCESS PID ?? don't know, not needed
135 break;
136 }
137 }
138 if (l!=i)
139 cs_log("WARNING: ECM-request corrupt");
140 else
141 get_cw(er);
142}
143
144static void radegast_process_unknown(uchar *buf)
145{
146 uchar answer[2]={0x81, 0x00};
147 radegast_send(answer);
148 cs_log("unknown request %02X, len=%d", buf[0], buf[1]);
149}
150
151static void radegast_server()
152{
153 int n;
154
155 radegast_auth_client(client[cs_idx].ip);
156 while ((n=get_request(mbuf))>0)
157 {
158 switch(mbuf[0])
159 {
160 case 1:
161 radegast_process_ecm(mbuf+2, mbuf[1]);
162 break;
163 default:
164 radegast_process_unknown(mbuf);
165 }
166 }
167 cs_disconnect_client();
168}
169
170static int radegast_send_ecm(ECM_REQUEST *er)
171{
172 int n;
173 uchar provid_buf[8];
174 uchar header[22] = "\x02\x01\x00\x06\x08\x30\x30\x30\x30\x30\x30\x30\x30\x07\x04\x30\x30\x30\x38\x08\x01\x02";
175 uchar *ecmbuf = malloc(er->l + 30);
176 memset(ecmbuf, 0, er->l + 30);
177
178 ecmbuf[0] = 1;
179 ecmbuf[1] = er->l + 30 - 2;
180 memcpy(ecmbuf + 2, header, sizeof(header));
181 for(n = 0; n < 4; n++) {
182 sprintf((char*)provid_buf+(n*2), "%02X", ((uchar *)(&er->prid))[4 - 1 - n]);
183 }
184 ecmbuf[7] = provid_buf[0];
185 ecmbuf[8] = provid_buf[1];
186 ecmbuf[9] = provid_buf[2];
187 ecmbuf[10] = provid_buf[3];
188 ecmbuf[11] = provid_buf[4];
189 ecmbuf[12] = provid_buf[5];
190 ecmbuf[13] = provid_buf[6];
191 ecmbuf[14] = provid_buf[7];
192 ecmbuf[2 + sizeof(header)] = 0xa;
193 ecmbuf[3 + sizeof(header)] = 2;
194 ecmbuf[4 + sizeof(header)] = er->caid >> 8;
195 ecmbuf[5 + sizeof(header)] = er->caid & 0xff;
196 ecmbuf[6 + sizeof(header)] = 3;
197 ecmbuf[7 + sizeof(header)] = er->l;
198 memcpy(ecmbuf + 8 + sizeof(header), er->ecm, er->l);
199 ecmbuf[4] = er->caid >> 8;
200
201 reader[ridx].msg_idx = er->idx;
202 n = send(pfd, ecmbuf, er->l + 30, 0);
203
204 cs_log("radegast: sending ecm");
205 cs_ddump(ecmbuf, er->l + 30, "ecm:");
206
207 free(ecmbuf);
208
209 return 0;
210}
211
212int radegast_cli_init(void)
213{
214 static struct sockaddr_in loc_sa;
215 struct protoent *ptrp;
216 int p_proto, handle;
217
218 pfd=0;
219 if (reader[ridx].r_port<=0)
220 {
221 cs_log("radegast: invalid port %d for server %s", reader[ridx].r_port, reader[ridx].device);
222 return(1);
223 }
224 if( (ptrp=getprotobyname("tcp")) )
225 p_proto=ptrp->p_proto;
226 else
227 p_proto=6;
228
229 client[cs_idx].ip=0;
230 memset((char *)&loc_sa,0,sizeof(loc_sa));
231 loc_sa.sin_family = AF_INET;
232#ifdef LALL
233 if (cfg->serverip[0])
234 loc_sa.sin_addr.s_addr = inet_addr(cfg->serverip);
235 else
236#endif
237 loc_sa.sin_addr.s_addr = INADDR_ANY;
238 loc_sa.sin_port = htons(reader[ridx].l_port);
239
240 if ((client[cs_idx].udp_fd=socket(PF_INET, SOCK_STREAM, p_proto))<0)
241 {
242 cs_log("cccam: Socket creation failed (errno=%d)", errno);
243 cs_exit(1);
244 }
245
246#ifdef SO_PRIORITY
247 if (cfg->netprio)
248 setsockopt(client[cs_idx].udp_fd, SOL_SOCKET, SO_PRIORITY,
249 (void *)&cfg->netprio, sizeof(ulong));
250#endif
251 if (!reader[ridx].tcp_ito) {
252 ulong keep_alive = reader[ridx].tcp_ito?1:0;
253 setsockopt(client[cs_idx].udp_fd, SOL_SOCKET, SO_KEEPALIVE,
254 (void *)&keep_alive, sizeof(ulong));
255 }
256
257 memset((char *)&client[cs_idx].udp_sa,0,sizeof(client[cs_idx].udp_sa));
258 client[cs_idx].udp_sa.sin_family = AF_INET;
259 client[cs_idx].udp_sa.sin_port = htons((u_short)reader[ridx].r_port);
260
261 struct hostent *server;
262 server = gethostbyname(reader[ridx].device);
263 memmove((char *)&client[cs_idx].udp_sa.sin_addr.s_addr, (char *)server->h_addr, server->h_length);
264
265 cs_log("radegast: proxy %s:%d (fd=%d)",
266 reader[ridx].device, reader[ridx].r_port, client[cs_idx].udp_fd);
267
268 handle = network_tcp_connection_open();
269 if(handle < 0) return -1;
270
271 reader[ridx].tcp_connected = 1;
272 reader[ridx].last_g = reader[ridx].last_s = time((time_t *)0);
273
274 cs_debug("radegast: last_s=%d, last_g=%d", reader[ridx].last_s, reader[ridx].last_g);
275
276 pfd=client[cs_idx].udp_fd;
277
278 return(0);
279}
280
281void module_radegast(struct s_module *ph)
282{
283 static PTAB ptab;
284 ptab.ports[0].s_port = cfg->rad_port;
285 ph->ptab = &ptab;
286 ph->ptab->nports = 1;
287
288 strcpy(ph->desc, "radegast");
289 ph->type=MOD_CONN_TCP;
290 ph->multi=0;
291 ph->watchdog=1;
292 ph->s_ip=cfg->rad_srvip;
293 ph->s_handler=radegast_server;
294 ph->recv=radegast_recv;
295 ph->send_dcw=radegast_send_dcw;
296 ph->c_multi=0;
297 ph->c_init=radegast_cli_init;
298 ph->c_recv_chk=radegast_recv_chk;
299 ph->c_send_ecm=radegast_send_ecm;
300}
Note: See TracBrowser for help on using the repository browser.