]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/atm/atmarpd/atmarpd.c
unfinished sblive driver, playback/mixer only for now - not enabled in
[FreeBSD/FreeBSD.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$
27  *
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 <stdio.h>
56 #include <string.h>
57 #include <syslog.h>
58 #include <unistd.h>
59
60 #include "../scspd/scsp_msg.h"
61 #include "../scspd/scsp_if.h"
62 #include "../scspd/scsp_var.h"
63 #include "atmarp_var.h"
64
65 #ifndef lint
66 __RCSID("@(#) $FreeBSD$");
67 #endif
68
69
70 /*
71  * Global variables
72  */
73 char            *prog;
74 int             atmarp_debug_mode = 0;
75 int             atmarp_max_socket = 0;
76 Atmarp_intf     *atmarp_intf_head = (Atmarp_intf *)0;
77 Atmarp_slis     *atmarp_slis_head = (Atmarp_slis *)0;
78 FILE            *atmarp_log_file = (FILE *)0;
79 char            *atmarp_log_file_name = (char *)0;
80 Harp_timer      cache_timer, perm_timer;
81
82
83 /*
84  * Print a usage message
85  *
86  * Arguments:
87  *      none
88  *
89  * Returns:
90  *      exits, does not return
91  *
92  */
93 void
94 usage()
95 {
96         fprintf(stderr, "usage: %s [-d] [-l <log_file>] <net_intf> ...\n", prog);
97         exit(1);
98 }
99
100
101 /*
102  * Process command line parameters
103  *
104  * Arguments:
105  *      argc    number of command-line arguments
106  *      argv    list of pointers to command-line arguments
107  *
108  * Returns:
109  *      none
110  *
111  */
112 static void
113 initialize(argc, argv)
114         int     argc;
115         char    *argv[];
116
117 {
118         int     i, rc;
119
120         /*
121          * Save program name, ignoring any path components
122          */
123         if ((prog = (char *)strrchr(argv[0], '/')) != NULL)
124                 prog++;
125         else
126                 prog = argv[0];
127
128         /*
129          * Make sure we're being invoked by the super user
130          */
131         i = getuid();
132         if (i != 0) {
133                 fprintf(stderr, "%s: You must be root to run this program\n",
134                                 prog);
135                 exit(1);
136         }
137
138         /*
139          * Scan arguments, checking for options
140          */
141         for (i = 1; i < argc; i++) {
142                 if (argv[i][0] == '-') {
143                         if (strcmp(argv[i], "-d") == 0) {
144                                 atmarp_debug_mode = TRUE;
145                         } else if (strcmp(argv[i], "-l") == 0) {
146                                 i++;
147                                 if (i >= argc) {
148                                         fprintf(stderr, "%s: Log file name missing\n",
149                                                 prog);
150                                         exit(1);
151                                 }
152                                 atmarp_log_file_name = argv[i];
153                         } else {
154                                 fprintf(stderr, "%s: Unrecognized option \"%s\"\n",
155                                                 prog, argv[i]);
156                                 exit(1);
157                         }
158                 } else {
159                         /*
160                          * Parameter is a network interface name
161                          */
162                         rc = atmarp_cfg_netif(argv[i]);
163                         if (rc) {
164                                 fprintf(stderr, "%s: Error configuring network interface %s\n",
165                                                 prog, argv[i]);
166                                 exit(1);
167                         }
168                 }
169         }
170
171         /*
172          * Make sure we had at least one interface configured
173          */
174         if (!atmarp_intf_head) {
175                 usage();
176         }
177 }
178
179
180 /*
181  * Daemon housekeeping
182  *
183  * Arguments:
184  *      None
185  *
186  * Returns:
187  *      None
188  *
189  */
190 static void
191 start_daemon()
192
193 {
194         int     dpid, fd, file_count, rc;
195
196         /*
197          * Ignore selected signals
198          */
199 #ifdef SIGTTOU
200         signal(SIGTTOU, SIG_IGN);
201 #endif
202 #ifdef SIGTTIN
203         signal(SIGTTIN, SIG_IGN);
204 #endif
205 #ifdef SIGTSTP
206         signal(SIGTSTP, SIG_IGN);
207 #endif
208 #ifdef SIGPIPE
209         signal(SIGPIPE, SIG_IGN);
210 #endif
211
212         /*
213          * Skip putting things into the background if we're
214          * in debugging mode
215          */
216         if (atmarp_debug_mode)
217                 goto daemon_bypass;
218
219         /*
220          * Set up syslog for error logging
221          */
222         if (!atmarp_log_file) {
223                 openlog(prog, LOG_PID | LOG_CONS, LOG_DAEMON);
224         }
225
226         /*
227          * Put the daemon into the background
228          */
229         dpid = fork();
230         if (dpid < 0) {
231                 atmarp_log(LOG_ERR, "fork failed");
232                 exit(1);
233         }
234         if (dpid > 0) {
235                 /*
236                  * This is the parent process--just exit and let
237                  * the daughter do all the work
238                  */
239                 exit(0);
240         }
241
242         /*
243          * Disassociate from any controlling terminal
244          */
245         rc = setpgrp(0, getpid());
246         if (rc < 0) {
247                 atmarp_log(LOG_ERR, "can't change process group");
248                 exit(1);
249         }
250         fd = open("/dev/tty", O_RDWR);
251         if (fd >= 0) {
252                 ioctl(fd, TIOCNOTTY, (char *)0);
253                 close(fd);
254         }
255
256         /*
257          * Close all open file descriptors
258          */
259         file_count = getdtablesize();
260         for (fd=0; fd<file_count; fd++) {
261                 close(fd);
262         }
263
264         /*
265          * Open log file, if specified
266          */
267         if (atmarp_log_file_name) {
268                 atmarp_log_file = fopen(atmarp_log_file_name, "a");
269                 if (!atmarp_log_file) {
270                         atmarp_log(LOG_ERR, "%s: Can't open log file \'%s\'\n",
271                                         prog, atmarp_log_file_name);
272                         exit(1);
273                 }
274         }
275
276         /*
277          * Set up and start interval timer
278          */
279 daemon_bypass:
280         init_timer();
281
282         /*
283          * Move to a safe directory
284          */
285         chdir(ATMARP_DIR);
286
287         /*
288          * Clear the file mode creation mask
289          */
290         umask(0);
291
292
293         /*
294          * Set up signal handlers
295          */
296         rc = (int)signal(SIGINT, atmarp_sigint);
297         if (rc == -1) {
298                 atmarp_log(LOG_ERR, "SIGINT signal setup failed");
299                 exit(1);
300         }
301 }
302
303
304 /*
305  * Main line code
306  *
307  * The ATMARP server resides in the kernel, while SCSP runs as a daemon
308  * in user space.  This program exists to provide an interface between
309  * the two.  It periodically polls the kernel to get the ATMARP cache
310  * and passes information about new entries to SCSP.  It also accepts
311  * new information from SCSP and passes it to the kernel.
312  *
313  * Arguments:
314  *      argc    number of command-line arguments
315  *      argv    list of pointers to command-line arguments
316  *
317  * Returns:
318  *      none
319  *
320  */
321 int
322 main(argc, argv)
323         int     argc;
324         char    *argv[];
325
326 {
327         int             i, rc;
328         fd_set          read_set, write_set, except_set;
329         Atmarp_intf     *aip;
330
331         /*
332          * Process command line arguments
333          */
334         initialize(argc, argv);
335
336         /*
337          * Put the daemon into the background
338          */
339         start_daemon();
340
341         /*
342          * Start the cache update timer
343          */
344         HARP_TIMER(&cache_timer, ATMARP_CACHE_INTERVAL,
345                         atmarp_cache_timeout);
346
347         /*
348          * Start the permanent cache entry timer
349          */
350         HARP_TIMER(&perm_timer, ATMARP_PERM_INTERVAL,
351                         atmarp_perm_timeout);
352
353         /*
354          * Establish a connection to SCSP for each interface.  If a
355          * connect fails, it will be retried when the cache update
356          * timer fires.
357          */
358         for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
359                 if (atmarp_if_ready(aip)) {
360                         (void)atmarp_scsp_connect(aip);
361                 }
362         }
363
364         /*
365          * Read the cache from the kernel
366          */
367         atmarp_get_updated_cache();
368
369         /*
370          * Main program loop -- wait for data to come in from SCSP.
371          * When the timer fires, it will be handled elsewhere.
372          */
373         while (1) {
374                 /*
375                  * Wait for input from SCSP
376                  */
377                 FD_ZERO(&read_set);
378                 FD_ZERO(&write_set);
379                 FD_ZERO(&except_set);
380                 for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
381                         if (aip->ai_scsp_sock != -1) {
382                                 FD_SET(aip->ai_scsp_sock, &read_set);
383                         }
384                 }
385                 rc = select(atmarp_max_socket + 1,
386                                 &read_set, &write_set,
387                                 &except_set, (struct timeval *)0);
388                 if (rc < 0) {
389                         if (harp_timer_exec) {
390                                 timer_proc();
391                                 continue;
392                         } else if (errno == EINTR) {
393                                 continue;
394                         } else {
395                                 atmarp_log(LOG_ERR, "Select failed");
396                                 abort();
397                         }
398                 }
399
400                 /*
401                  * Read and process the input from SCSP
402                  */
403                 for (i = 0; i <= atmarp_max_socket; i++) {
404                         if (FD_ISSET(i, &read_set)) {
405                                 aip = atmarp_find_intf_sock(i);
406                                 if (aip)
407                                         rc = atmarp_scsp_read(aip);
408                         }
409                 }
410         }
411 }