Clean (void) casts from usr.sbin
[dragonfly.git] / usr.sbin / atm / atmarpd / atmarpd.c
1 /*
2  *
3  * ===================================
4  * HARP  |  Host ATM Research Platform
5  * ===================================
6  *
7  *
8  * This Host ATM Research Platform ("HARP") file (the "Software") is
9  * made available by Network Computing Services, Inc. ("NetworkCS")
10  * "AS IS".  NetworkCS does not provide maintenance, improvements or
11  * support of any kind.
12  *
13  * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14  * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15  * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16  * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17  * In no event shall NetworkCS be responsible for any damages, including
18  * but not limited to consequential damages, arising from or relating to
19  * any use of the Software or related support.
20  *
21  * Copyright 1994-1998 Network Computing Services, Inc.
22  *
23  * Copies of this Software may be made, however, the above copyright
24  * notice must be reproduced on all copies.
25  *
26  *      @(#) $FreeBSD: src/usr.sbin/atm/atmarpd/atmarpd.c,v 1.3.2.1 2000/12/11 01:03:29 obrien Exp $
27  *      @(#) $DragonFly: src/usr.sbin/atm/atmarpd/atmarpd.c,v 1.4 2004/12/18 22:48:02 swildner Exp $
28  */
29
30 /*
31  * Server Cache Synchronization Protocol (SCSP) Support
32  * ----------------------------------------------------
33  *
34  * SCSP-ATMARP server interface: main line code
35  *
36  */
37
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/socket.h>
41 #include <sys/stat.h>
42 #include <sys/ttycom.h>
43 #include <net/if.h>
44 #include <netinet/in.h>
45 #include <netatm/queue.h>
46 #include <netatm/atm.h>
47 #include <netatm/atm_if.h>
48 #include <netatm/atm_sap.h>
49 #include <netatm/atm_sys.h>
50 #include <netatm/atm_ioctl.h>
51
52 #include <errno.h>
53 #include <fcntl.h>
54 #include <libatm.h>
55 #include <paths.h>
56 #include <stdio.h>
57 #include <string.h>
58 #include <syslog.h>
59 #include <unistd.h>
60
61 #include "../scspd/scsp_msg.h"
62 #include "../scspd/scsp_if.h"
63 #include "../scspd/scsp_var.h"
64 #include "atmarp_var.h"
65
66 /*
67  * Global variables
68  */
69 char            *prog;
70 int             atmarp_debug_mode = 0;
71 int             atmarp_max_socket = 0;
72 Atmarp_intf     *atmarp_intf_head = (Atmarp_intf *)0;
73 Atmarp_slis     *atmarp_slis_head = (Atmarp_slis *)0;
74 FILE            *atmarp_log_file = (FILE *)0;
75 char            *atmarp_log_file_name = (char *)0;
76 Harp_timer      cache_timer, perm_timer;
77
78
79 /*
80  * Print a usage message
81  *
82  * Arguments:
83  *      none
84  *
85  * Returns:
86  *      exits, does not return
87  *
88  */
89 void
90 usage(void)
91 {
92         fprintf(stderr, "usage: %s [-d] [-l <log_file>] <net_intf> ...\n", prog);
93         exit(1);
94 }
95
96
97 /*
98  * Process command line parameters
99  *
100  * Arguments:
101  *      argc    number of command-line arguments
102  *      argv    list of pointers to command-line arguments
103  *
104  * Returns:
105  *      none
106  *
107  */
108 static void
109 initialize(int argc, char **argv)
110
111 {
112         int     i, rc;
113
114         /*
115          * Save program name, ignoring any path components
116          */
117         if ((prog = (char *)strrchr(argv[0], '/')) != NULL)
118                 prog++;
119         else
120                 prog = argv[0];
121
122         /*
123          * Make sure we're being invoked by the super user
124          */
125         i = getuid();
126         if (i != 0) {
127                 fprintf(stderr, "%s: You must be root to run this program\n",
128                                 prog);
129                 exit(1);
130         }
131
132         /*
133          * Scan arguments, checking for options
134          */
135         for (i = 1; i < argc; i++) {
136                 if (argv[i][0] == '-') {
137                         if (strcmp(argv[i], "-d") == 0) {
138                                 atmarp_debug_mode = TRUE;
139                         } else if (strcmp(argv[i], "-l") == 0) {
140                                 i++;
141                                 if (i >= argc) {
142                                         fprintf(stderr, "%s: Log file name missing\n",
143                                                 prog);
144                                         exit(1);
145                                 }
146                                 atmarp_log_file_name = argv[i];
147                         } else {
148                                 fprintf(stderr, "%s: Unrecognized option \"%s\"\n",
149                                                 prog, argv[i]);
150                                 exit(1);
151                         }
152                 } else {
153                         /*
154                          * Parameter is a network interface name
155                          */
156                         rc = atmarp_cfg_netif(argv[i]);
157                         if (rc) {
158                                 fprintf(stderr, "%s: Error configuring network interface %s\n",
159                                                 prog, argv[i]);
160                                 exit(1);
161                         }
162                 }
163         }
164
165         /*
166          * Make sure we had at least one interface configured
167          */
168         if (!atmarp_intf_head) {
169                 usage();
170         }
171 }
172
173
174 /*
175  * Daemon housekeeping
176  *
177  * Arguments:
178  *      None
179  *
180  * Returns:
181  *      None
182  *
183  */
184 static void
185 start_daemon(void)
186 {
187         int     dpid, fd, file_count, rc;
188
189         /*
190          * Ignore selected signals
191          */
192 #ifdef SIGTTOU
193         signal(SIGTTOU, SIG_IGN);
194 #endif
195 #ifdef SIGTTIN
196         signal(SIGTTIN, SIG_IGN);
197 #endif
198 #ifdef SIGTSTP
199         signal(SIGTSTP, SIG_IGN);
200 #endif
201 #ifdef SIGPIPE
202         signal(SIGPIPE, SIG_IGN);
203 #endif
204
205         /*
206          * Skip putting things into the background if we're
207          * in debugging mode
208          */
209         if (atmarp_debug_mode)
210                 goto daemon_bypass;
211
212         /*
213          * Set up syslog for error logging
214          */
215         if (!atmarp_log_file) {
216                 openlog(prog, LOG_PID | LOG_CONS, LOG_DAEMON);
217         }
218
219         /*
220          * Put the daemon into the background
221          */
222         dpid = fork();
223         if (dpid < 0) {
224                 atmarp_log(LOG_ERR, "fork failed");
225                 exit(1);
226         }
227         if (dpid > 0) {
228                 /*
229                  * This is the parent process--just exit and let
230                  * the daughter do all the work
231                  */
232                 exit(0);
233         }
234
235         /*
236          * Disassociate from any controlling terminal
237          */
238         rc = setpgrp(0, getpid());
239         if (rc < 0) {
240                 atmarp_log(LOG_ERR, "can't change process group");
241                 exit(1);
242         }
243         fd = open(_PATH_TTY, O_RDWR);
244         if (fd >= 0) {
245                 ioctl(fd, TIOCNOTTY, (char *)0);
246                 close(fd);
247         }
248
249         /*
250          * Close all open file descriptors
251          */
252         file_count = getdtablesize();
253         for (fd=0; fd<file_count; fd++) {
254                 close(fd);
255         }
256
257         /*
258          * Open log file, if specified
259          */
260         if (atmarp_log_file_name) {
261                 atmarp_log_file = fopen(atmarp_log_file_name, "a");
262                 if (!atmarp_log_file) {
263                         atmarp_log(LOG_ERR, "%s: Can't open log file \'%s\'\n",
264                                         prog, atmarp_log_file_name);
265                         exit(1);
266                 }
267         }
268
269         /*
270          * Set up and start interval timer
271          */
272 daemon_bypass:
273         init_timer();
274
275         /*
276          * Move to a safe directory
277          */
278         chdir(ATMARP_DIR);
279
280         /*
281          * Clear the file mode creation mask
282          */
283         umask(0);
284
285
286         /*
287          * Set up signal handlers
288          */
289         rc = (int)signal(SIGINT, atmarp_sigint);
290         if (rc == -1) {
291                 atmarp_log(LOG_ERR, "SIGINT signal setup failed");
292                 exit(1);
293         }
294 }
295
296
297 /*
298  * Main line code
299  *
300  * The ATMARP server resides in the kernel, while SCSP runs as a daemon
301  * in user space.  This program exists to provide an interface between
302  * the two.  It periodically polls the kernel to get the ATMARP cache
303  * and passes information about new entries to SCSP.  It also accepts
304  * new information from SCSP and passes it to the kernel.
305  *
306  * Arguments:
307  *      argc    number of command-line arguments
308  *      argv    list of pointers to command-line arguments
309  *
310  * Returns:
311  *      none
312  *
313  */
314 int
315 main(int argc, char **argv)
316 {
317         int             i, rc;
318         fd_set          read_set, write_set, except_set;
319         Atmarp_intf     *aip;
320
321         /*
322          * Process command line arguments
323          */
324         initialize(argc, argv);
325
326         /*
327          * Put the daemon into the background
328          */
329         start_daemon();
330
331         /*
332          * Start the cache update timer
333          */
334         HARP_TIMER(&cache_timer, ATMARP_CACHE_INTERVAL,
335                         atmarp_cache_timeout);
336
337         /*
338          * Start the permanent cache entry timer
339          */
340         HARP_TIMER(&perm_timer, ATMARP_PERM_INTERVAL,
341                         atmarp_perm_timeout);
342
343         /*
344          * Establish a connection to SCSP for each interface.  If a
345          * connect fails, it will be retried when the cache update
346          * timer fires.
347          */
348         for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
349                 if (atmarp_if_ready(aip)) {
350                         atmarp_scsp_connect(aip);
351                 }
352         }
353
354         /*
355          * Read the cache from the kernel
356          */
357         atmarp_get_updated_cache();
358
359         /*
360          * Main program loop -- wait for data to come in from SCSP.
361          * When the timer fires, it will be handled elsewhere.
362          */
363         while (1) {
364                 /*
365                  * Wait for input from SCSP
366                  */
367                 FD_ZERO(&read_set);
368                 FD_ZERO(&write_set);
369                 FD_ZERO(&except_set);
370                 for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
371                         if (aip->ai_scsp_sock != -1) {
372                                 FD_SET(aip->ai_scsp_sock, &read_set);
373                         }
374                 }
375                 rc = select(atmarp_max_socket + 1,
376                                 &read_set, &write_set,
377                                 &except_set, (struct timeval *)0);
378                 if (rc < 0) {
379                         if (harp_timer_exec) {
380                                 timer_proc();
381                                 continue;
382                         } else if (errno == EINTR) {
383                                 continue;
384                         } else {
385                                 atmarp_log(LOG_ERR, "Select failed");
386                                 abort();
387                         }
388                 }
389
390                 /*
391                  * Read and process the input from SCSP
392                  */
393                 for (i = 0; i <= atmarp_max_socket; i++) {
394                         if (FD_ISSET(i, &read_set)) {
395                                 aip = atmarp_find_intf_sock(i);
396                                 if (aip)
397                                         rc = atmarp_scsp_read(aip);
398                         }
399                 }
400         }
401 }