1 /*
2 * Tlf - contest logging program for amateur radio operators
3 * Copyright (C) 2001-2002-2003 Rein Couperus <pa0rct@amsat.org>
4 * 2013 Fred DH5FS
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <netdb.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <syslog.h>
28 #include <time.h>
29 #include <unistd.h>
30 #include <arpa/inet.h>
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33
34 #include "err_utils.h"
35 #include "lancode.h"
36 #include "tlf.h"
37 #include "tlf_curses.h"
38
39
40 int lan_socket_descriptor;
41 struct sockaddr_in lan_sin;
42 int lan_bind_rc, lan_close_rc;
43 ssize_t lan_recv_rc;
44 long lan_save_file_flags;
45 char lan_recv_message[256];
46 char lan_message[256];
47 char lan_logline[256];
48 unsigned int lan_sin_len;
49 //--------------------------------------
50 int bc_socket_descriptor[MAXNODES];
51 ssize_t bc_sendto_rc;
52 int bc_close_rc;
53 int cl_send_inhibit = 0;
54 char lanbuffer[255];
55 struct sockaddr_in bc_address[MAXNODES];
56 struct hostent *bc_hostbyname[MAXNODES];
57 /* host names and UDP ports to send notifications to */
58 char bc_hostaddress[MAXNODES][16];
59 char bc_hostservice[MAXNODES][16] = {
60 [0 ... MAXNODES - 1] = { [0 ... 15] = 0 }
61 };
62 char sendbuffer[256];
63 int nodes = 0;
64 int node;
65 int send_error_limit[MAXNODES];
66 //--------------------------------------
67 /* default port to listen for incomming packets and to send packet to */
68 char default_lan_service[16] = "6788";
69 /* lan port parsed from config */
70 int lan_port = 6788;
71
72 int lan_active = 0;
73 int send_error[MAXNODES];
74 int lan_mutex = 0;
75 int send_packets[MAXNODES];
76 int recv_error;
77 int recv_packets;
78 int buflen;
79 char talkarray[5][62];
80 freq_t node_frequencies[MAXNODES];
81 int lanqsos;
82 char lastqsonr[5];
83 int highqsonr;
84 int landebug = 0;
85 long lantime;
86 long timecorr;
87 int time_master;
88 char thisnode = 'A'; /* start with 'A' if not defined in
89 logcfg.dat */
90
91 //---------------------end lan globals --------------
92
resolveService(const char * service)93 int resolveService(const char *service) {
94 struct servent *service_ent;
95 service_ent = getservbyname(service, "udp");
96 int port = 0;
97 if (service_ent != NULL) {
98 port = ntohs(service_ent->s_port);
99 } else if (strlen(service) > 0) {
100 port = atoi(service);
101 }
102 if (port == 0) {
103 port = atoi(default_lan_service);
104 }
105 return port;
106 }
107
lanrecv_init(void)108 int lanrecv_init(void) {
109 if (lan_active == 0)
110 return (1);
111
112 sprintf(default_lan_service, "%d", lan_port);
113 bzero(&lan_sin, sizeof(lan_sin));
114 lan_sin.sin_family = AF_INET;
115 lan_sin.sin_addr.s_addr = htonl(INADDR_ANY);
116 lan_sin.sin_port = htons(resolveService(default_lan_service));
117 lan_sin_len = sizeof(lan_sin);
118
119 lan_socket_descriptor = socket(AF_INET, SOCK_DGRAM, 0);
120 if (lan_socket_descriptor == -1) {
121 syslog(LOG_ERR, "%s\n", "LAN: socket");
122 return (-1);
123 }
124
125 lan_bind_rc =
126 bind(lan_socket_descriptor, (struct sockaddr *) &lan_sin,
127 sizeof(lan_sin));
128 if (lan_bind_rc == -1) {
129 syslog(LOG_ERR, "%s\n", "LAN: bind");
130 return (-2);
131 }
132
133 lan_save_file_flags = fcntl(lan_socket_descriptor, F_GETFL);
134 lan_save_file_flags |= O_NONBLOCK;
135 if (fcntl(lan_socket_descriptor, F_SETFL, lan_save_file_flags) == -1) {
136 syslog(LOG_ERR, "%s\n", "trying non-blocking");
137 return (-3);
138 }
139 return (0);
140 }
141
lan_recv_close(void)142 int lan_recv_close(void) {
143
144 if (lan_active == 0)
145 return (-1);
146
147 lan_close_rc = close(lan_socket_descriptor);
148 if (lan_close_rc == -1) {
149 syslog(LOG_ERR, "%s\n", "LAN: close call failed");
150 return (errno);
151 }
152
153 return (0);
154 }
155
lan_recv(void)156 int lan_recv(void) {
157
158 if (lan_active == 0)
159 return (-1);
160
161 lan_recv_message[0] = '\0';
162
163 lan_recv_rc =
164 recvfrom(lan_socket_descriptor, lan_recv_message,
165 sizeof(lan_recv_message), 0, (struct sockaddr *) &lan_sin,
166 &lan_sin_len);
167
168 if (lan_recv_rc == -1 && errno != EAGAIN) {
169 recv_error++;
170 return (errno);
171 } else if (lan_recv_rc == 0 || errno == EAGAIN) { /* no data */
172 errno = 0; /* clear the error */
173 }
174
175 errno = 0; /* clear the error */
176
177 if (lan_recv_message[1] == CLUSTERMSG)
178 cl_send_inhibit = 1; // this node does not send cluster info
179
180 if (lan_recv_rc > 0)
181 recv_packets++;
182
183 strcpy(lan_message, lan_recv_message);
184 if (lan_recv_rc > buflen)
185 buflen = lan_recv_rc;
186
187 return (0);
188 }
189
190 // ----------------send routines --------------------------
191
lan_send_init(void)192 int lan_send_init(void) {
193
194 if (lan_active == 0)
195 return (1);
196
197 for (node = 0; node < nodes; node++) {
198
199 bc_hostbyname[node] = gethostbyname(bc_hostaddress[node]);
200 if (bc_hostbyname[node] == NULL) {
201 syslog(LOG_ERR, "%s\n", "LAN: gethostbyname failed");
202 return (-1);
203 }
204
205 bzero(&bc_address[node], sizeof(bc_address[node])); /* empty data structure */
206 bc_address[node].sin_family = AF_INET;
207 memcpy(&bc_address[node].sin_addr.s_addr, bc_hostbyname[node]->h_addr,
208 sizeof(bc_address[node].sin_addr.s_addr));
209
210 bc_address[node].sin_port = htons(resolveService(bc_hostservice[node]));
211
212 syslog(LOG_INFO, "open socket: to %d.%d.%d.%d:%d\n",
213 (ntohl(bc_address[node].sin_addr.s_addr) & 0xff000000) >> 24,
214 (ntohl(bc_address[node].sin_addr.s_addr) & 0x00ff0000) >> 16,
215 (ntohl(bc_address[node].sin_addr.s_addr) & 0x0000ff00) >> 8,
216 (ntohl(bc_address[node].sin_addr.s_addr) & 0x000000ff) >> 0,
217 ntohs(bc_address[node].sin_port));
218
219 bc_socket_descriptor[node] = socket(AF_INET, SOCK_DGRAM, 0);
220
221 if (bc_socket_descriptor[node] == -1) {
222 syslog(LOG_ERR, "%s\n", "LAN: socket call failed");
223 return (-1);
224 }
225 }
226
227 return (0);
228 }
229
lan_send_close(void)230 int lan_send_close(void) {
231
232 if (lan_active == 0)
233 return (-1);
234
235 for (node = 0; node < nodes; node++) {
236
237 bc_close_rc = close(bc_socket_descriptor[node]);
238 if (bc_close_rc == -1) {
239 syslog(LOG_ERR, "%s\n", "LAN: close call failed");
240 return (-1);
241 }
242 }
243
244 return (0);
245 }
246
lan_send(char * lanbuffer)247 int lan_send(char *lanbuffer) {
248
249 if (lan_active == 0)
250 return (-1);
251
252 for (node = 0; node < nodes; node++) {
253
254 if (lanbuffer[0] != '\0') {
255 bc_sendto_rc = sendto(bc_socket_descriptor[node],
256 lanbuffer, 256,
257 0, (struct sockaddr *) &bc_address[node],
258 sizeof(bc_address[node]));
259
260 }
261
262 if (bc_sendto_rc == -1) {
263 if (send_error[node] >= (send_error_limit[node] + 10)) {
264 TLF_LOG_INFO("LAN: send problem...!");
265 send_error_limit[node] += 10;
266 } else
267 send_error[node]++;
268
269 } else
270 send_packets[node]++;
271 }
272
273 lanbuffer[0] = '\0';
274
275 return (0);
276 }
277
278 /* ----------------- send lan message ----------*/
279
send_lan_message(int opcode,char * message)280 int send_lan_message(int opcode, char *message) {
281 char sendbuffer[102];
282
283 sendbuffer[0] = thisnode;
284 sendbuffer[1] = opcode;
285 sendbuffer[2] = '\0';
286 strncat(sendbuffer, message, 98);
287 if (opcode == CLUSTERMSG) {
288 if (cl_send_inhibit == 0) {
289 strcat(sendbuffer, "\n");
290 lan_send(sendbuffer);
291 }
292 }
293
294 if (opcode == LOGENTRY) {
295 sendbuffer[82] = '\0';
296
297 lan_send(sendbuffer);
298 }
299
300 if (opcode == TLFSPOT) {
301 sendbuffer[82] = '\0';
302 lan_send(sendbuffer);
303 }
304 if (opcode == TLFMSG) {
305 sendbuffer[82] = '\0';
306 lan_send(sendbuffer);
307 }
308 if (opcode == FREQMSG) {
309 sendbuffer[10] = '\0';
310 lan_send(sendbuffer);
311 }
312 if (opcode == INCQSONUM) {
313 strcat(sendbuffer, "\n");
314 lan_send(sendbuffer);
315 }
316 if (opcode == TIMESYNC) {
317 sendbuffer[14] = '\0';
318 lan_send(sendbuffer);
319 }
320 if (opcode == QTCRENTRY) {
321 strcat(sendbuffer, "\n");
322 sendbuffer[94] = '\0';
323 lan_send(sendbuffer);
324 }
325 if (opcode == QTCSENTRY) {
326 strcat(sendbuffer, "\n");
327 sendbuffer[100] = '\0';
328 lan_send(sendbuffer);
329 }
330 if (opcode == QTCFLAG) {
331 strcat(sendbuffer, "\n");
332 lan_send(sendbuffer);
333 }
334
335 return (0);
336 }
337
338 /* ----------------- send talk message ----------*/
talk(void)339 void talk(void) {
340
341 char talkline[61] = "";
342
343 mvprintw(LINES - 1, 0, backgrnd_str);
344 mvprintw(LINES - 1, 0, "T>");
345 refreshp();
346 echo();
347 getnstr(talkline, 60);
348 noecho();
349
350 strcat(talkline, "\n");
351
352 send_lan_message(TLFMSG, talkline);
353
354 talkline[0] = '\0';
355 attron(COLOR_PAIR(C_HEADER));
356 mvprintw(LINES - 1, 0, backgrnd_str);
357 refreshp();
358 }
359
360 /* ----------------- send freq. message ----------*/
361
send_freq(freq_t freq)362 int send_freq(freq_t freq) {
363
364 extern int bandinx;
365 extern int trx_control;
366
367 char fbuffer[8];
368
369 if (trx_control == 1) {
370
371 sprintf(fbuffer, "%7.1f", freq / 1000.0);
372 } else {
373 switch (bandinx) {
374
375 case 0:
376 sprintf(fbuffer, " 160.0");
377 break;
378
379 case 1:
380 sprintf(fbuffer, " 80.0");
381 break;
382
383 case 2:
384 sprintf(fbuffer, " 40.0");
385 break;
386
387 case 3:
388 sprintf(fbuffer, " 30.0");
389 break;
390
391 case 4:
392 sprintf(fbuffer, " 20.0");
393 break;
394
395 case 5:
396 sprintf(fbuffer, " 17.0");
397 break;
398
399 case 6:
400 sprintf(fbuffer, " 15.0");
401 break;
402
403 case 7:
404 sprintf(fbuffer, " 12.0");
405 break;
406
407 case 8:
408 sprintf(fbuffer, " 10.0");
409 break;
410
411 default:
412 sprintf(fbuffer, " ");
413 }
414 }
415
416 send_lan_message(FREQMSG, fbuffer);
417
418 return (0);
419 }
420
421 /* ----------------- send time message ----------*/
422
send_time(void)423 int send_time(void) {
424
425 extern int timeoffset;
426
427 long now;
428 char timebuffer[14];
429
430 now = (long)(time(0) + (timeoffset * 3600L));
431
432 sprintf(timebuffer, "%ld", now);
433 strcat(timebuffer, " ");
434 send_lan_message(TIMESYNC, timebuffer);
435
436 return (0);
437 }
438