~ubuntu-branches/ubuntu/precise/netatalk/precise

« back to all changes in this revision

Viewing changes to etc/atalkd/main.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Rittau
  • Date: 2004-01-19 12:43:49 UTC
  • Revision ID: james.westby@ubuntu.com-20040119124349-es563jbp0hk0ae51
Tags: upstream-1.6.4
ImportĀ upstreamĀ versionĀ 1.6.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Id: main.c,v 1.17 2002/10/05 13:20:13 didg Exp $
 
3
 *
 
4
 * Copyright (c) 1990,1993 Regents of The University of Michigan.
 
5
 * All Rights Reserved. See COPYRIGHT.
 
6
 */
 
7
 
 
8
#ifdef HAVE_CONFIG_H
 
9
#include "config.h"
 
10
#endif /* HAVE_CONFIG_H */
 
11
 
 
12
#include <sys/param.h>
 
13
#include <sys/socket.h>
 
14
#if defined( sun ) && defined( __svr4__ )
 
15
#include </usr/ucbinclude/sys/file.h>
 
16
#else /* sun __svr4__ */
 
17
#include <sys/file.h>
 
18
#endif /* sun __svr4__ */
 
19
#include <sys/time.h>
 
20
#include <sys/resource.h>
 
21
#include <sys/ioctl.h>
 
22
 
 
23
/* POSIX.1 check */
 
24
#include <sys/types.h>
 
25
#ifdef HAVE_SYS_WAIT_H
 
26
#include <sys/wait.h>
 
27
#endif /* HAVE_SYS_WAIT_H */
 
28
#ifndef WEXITSTATUS 
 
29
#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
 
30
#endif /* ! WEXITSTATUS */
 
31
#ifndef WIFEXITED
 
32
#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
 
33
#endif /* ! WIFEXITED */
 
34
#ifndef WIFSTOPPED
 
35
#define WIFSTOPPED(status) (((status) & 0xff) == 0x7f)
 
36
#endif
 
37
 
 
38
#include <errno.h>
 
39
#ifdef TRU64
 
40
#include <sys/mbuf.h>
 
41
#include <net/route.h>
 
42
#endif /* TRU64 */
 
43
#include <net/if.h>
 
44
#include <net/route.h>
 
45
 
 
46
#include <netinet/in.h>
 
47
 
 
48
#include <signal.h>
 
49
#include <atalk/logger.h>
 
50
#include <stdio.h>
 
51
#include <stdlib.h>
 
52
#include <string.h>
 
53
#include <netdb.h>
 
54
#include <fcntl.h>
 
55
#include <unistd.h>
 
56
 
 
57
#include <netatalk/endian.h>
 
58
#include <netatalk/at.h>
 
59
#include <atalk/compat.h>
 
60
#include <atalk/zip.h>
 
61
#include <atalk/rtmp.h>
 
62
#include <atalk/ddp.h>
 
63
#include <atalk/atp.h>
 
64
#include <atalk/paths.h>
 
65
#include <atalk/util.h>
 
66
 
 
67
#ifdef __svr4__
 
68
#include <sys/sockio.h>
 
69
#include <termios.h>
 
70
#endif /* __svr4__ */
 
71
 
 
72
#include "interface.h"
 
73
#include "gate.h"
 
74
#include "list.h"
 
75
#include "rtmp.h"
 
76
#include "zip.h"
 
77
#include "atserv.h"
 
78
#include "main.h"
 
79
 
 
80
/* Forward Declarations */
 
81
int ifconfig(const char *iname, unsigned long cmd, struct sockaddr_at *sa);
 
82
 
 
83
/* FIXME/SOCKLEN_T: socklen_t is a unix98 feature */
 
84
#ifndef SOCKLEN_T
 
85
#define SOCKLEN_T unsigned int
 
86
#endif /* SOCKLEN_T */
 
87
 
 
88
#ifndef WEXITSTATUS
 
89
#define WEXITSTATUS(x)  ((x).w_retcode)
 
90
#endif /* WEXITSTATUS */
 
91
 
 
92
/* linux has a special ioctl for appletalk device destruction.  as of
 
93
 * 2.1.57, SIOCDIFADDR works w/ linux. okay, we need to deal with the
 
94
 * fact that SIOCDIFADDR may be defined on linux despite the fact that
 
95
 * it doesn't work. */
 
96
#if !defined(SIOCDIFADDR) && defined(SIOCATALKDIFADDR)
 
97
#define SIOCDIFADDR SIOCATALKDIFADDR
 
98
#endif
 
99
 
 
100
#define elements(a)     (sizeof(a)/sizeof((a)[0]))
 
101
 
 
102
#define PKTSZ   1024
 
103
 
 
104
extern int      rtmp_packet();
 
105
extern int      nbp_packet();
 
106
extern int      aep_packet();
 
107
extern int      zip_packet();
 
108
 
 
109
int             rtfd;
 
110
 
 
111
struct atserv   atserv[] = {
 
112
    { "rtmp",           1,      rtmp_packet },          /* 0 */
 
113
    { "nbp",            2,      nbp_packet },           /* 1 */
 
114
    { "echo",           4,      aep_packet },           /* 2 */
 
115
    { "zip",            6,      zip_packet },           /* 3 */
 
116
};
 
117
int             atservNATSERV = elements( atserv );
 
118
 
 
119
struct interface        *interfaces = NULL, *ciface = NULL;
 
120
 
 
121
int             debug = 0, quiet = 0, chatty = 0;
 
122
char            *configfile = NULL;
 
123
int             ziptimeout = 0, transition = 0;
 
124
int             stabletimer, stable = 0, newrtmpdata = 0, noparent = 0;
 
125
static int      ninterfaces;
 
126
int             defphase = IFACE_PHASE2;
 
127
int             nfds = 0;
 
128
fd_set          fds;
 
129
char            Packet[ PKTSZ ];
 
130
char            *version = VERSION;
 
131
static char     *pidfile = _PATH_ATALKDLOCK;
 
132
 
 
133
 
 
134
/* from config.c */
 
135
 
 
136
int readconf( char * );
 
137
int getifconf( void );
 
138
int writeconf( char * );
 
139
 
 
140
/* this is the messiest of the bunch as atalkd can exit pretty much
 
141
 * everywhere. we delete interfaces here instead of in as_down. */
 
142
static void atalkd_exit(const int i)
 
143
{
 
144
#ifdef SIOCDIFADDR
 
145
  struct interface *iface;
 
146
 
 
147
  for (iface = interfaces; iface; iface = iface->i_next) {
 
148
    if (ifconfig( iface->i_name, SIOCDIFADDR, &iface->i_addr)) {
 
149
#ifdef SIOCATALKDIFADDR
 
150
#if (SIOCDIFADDR != SIOCATALKDIFADDR)
 
151
      if (!ifconfig(iface->i_name, SIOCATALKDIFADDR, &iface->i_addr)) 
 
152
        continue;
 
153
#endif /* SIOCDIFADDR != SIOCATALKDIFADDR */
 
154
#endif /* SIOCATALKIFADDR */
 
155
      LOG(log_error, logtype_atalkd, "difaddr(%u.%u): %s", 
 
156
              ntohs(iface->i_addr.sat_addr.s_net), 
 
157
              iface->i_addr.sat_addr.s_node, strerror(errno));
 
158
    }
 
159
  }
 
160
#endif /* SOPCDOFADDR */
 
161
 
 
162
  server_unlock(pidfile);
 
163
  exit(i);
 
164
}
 
165
 
 
166
 
 
167
static void as_timer(int sig)
 
168
{
 
169
    struct sockaddr_at  sat;
 
170
    struct ziphdr       zh;
 
171
    struct rtmp_head    rh;
 
172
    struct rtmp_tuple   rt;
 
173
    struct atport       *ap, *zap, *rap;
 
174
    struct interface    *iface, *iface2;
 
175
    struct gate         *gate, *fgate = NULL;
 
176
    struct rtmptab      *rtmp, *frtmp;
 
177
    struct ziptab       *zt;
 
178
    char                *data, *end, packet[ ATP_BUFSIZ ];
 
179
    int                 sentzipq = 0;
 
180
    int                 n, cc;
 
181
 
 
182
    memset(&sat, 0, sizeof( struct sockaddr_at ));
 
183
    for ( iface = interfaces; iface; iface = iface->i_next ) {
 
184
        if ( iface->i_flags & IFACE_LOOPBACK ) {
 
185
            continue;
 
186
        }
 
187
        for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
 
188
            if ( ap->ap_packet == zip_packet ) {
 
189
                zap = ap;
 
190
            }
 
191
            if ( ap->ap_packet == rtmp_packet ) {
 
192
                rap = ap;
 
193
            }
 
194
        }
 
195
 
 
196
        if (( iface->i_flags & ( IFACE_ADDR|IFACE_CONFIG|IFACE_NOROUTER )) ==
 
197
                IFACE_ADDR ) {
 
198
            if ( iface->i_time < 3 ) {
 
199
                if ( iface->i_flags & IFACE_PHASE1 ) {
 
200
                  if (rtmp_request( iface ) < 0) {
 
201
                      LOG(log_error, logtype_atalkd, "rtmp_request: %s", strerror(errno));
 
202
                      atalkd_exit(1);
 
203
                  }
 
204
                    newrtmpdata = 1;
 
205
                } else {
 
206
                  if (zip_getnetinfo( iface ) < 0) {
 
207
                    LOG(log_error, logtype_atalkd, "zip_getnetinfo: %s", strerror(errno));
 
208
                    atalkd_exit(1);
 
209
                  }
 
210
                  sentzipq = 1;
 
211
                }
 
212
                iface->i_time++;
 
213
            } else {
 
214
                iface->i_flags |= IFACE_NOROUTER;
 
215
                if ((iface->i_flags & IFACE_ISROUTER)) {
 
216
                    if (( iface->i_flags & IFACE_SEED ) == 0 ) {
 
217
                        /*
 
218
                         * No seed info, and we've got multiple interfaces.
 
219
                         * Wait forever.
 
220
                         */
 
221
                        LOG(log_info, logtype_atalkd,
 
222
                                "as_timer multiple interfaces, no seed" );
 
223
                        LOG(log_info, logtype_atalkd, "as_timer can't configure %s",
 
224
                                iface->i_name );
 
225
                        LOG(log_info, logtype_atalkd, "as_timer waiting for router" );
 
226
                        iface->i_time = 0;
 
227
                        continue;
 
228
                    } else {
 
229
                        /*
 
230
                         * Complete configuration for iface, and boot next
 
231
                         * interface.
 
232
                         */
 
233
                        iface->i_flags |= IFACE_CONFIG;
 
234
                        for ( zt = iface->i_czt; zt; zt = zt->zt_next ) {
 
235
                            if (addzone( iface->i_rt, zt->zt_len, 
 
236
                                         zt->zt_name) < 0) {
 
237
                              LOG(log_error, logtype_atalkd, "addzone: %s", strerror(errno));
 
238
                              atalkd_exit(1);
 
239
                            }
 
240
                        }
 
241
                        if ( iface->i_rt->rt_zt ) {
 
242
                            iface->i_rt->rt_flags &= ~RTMPTAB_ZIPQUERY;
 
243
                            iface->i_rt->rt_flags |= RTMPTAB_HASZONES;
 
244
                        }
 
245
                        if ( iface->i_flags & IFACE_PHASE1 ) {
 
246
                            LOG(log_info, logtype_atalkd,
 
247
                                    "as_timer configured %s phase 1 from seed",
 
248
                                    iface->i_name );
 
249
                            setaddr( iface, IFACE_PHASE1,
 
250
                                    iface->i_caddr.sat_addr.s_net,
 
251
                                    iface->i_addr.sat_addr.s_node,
 
252
                                    iface->i_caddr.sat_addr.s_net,
 
253
                                    iface->i_caddr.sat_addr.s_net );
 
254
                        } else {
 
255
                            LOG(log_info, logtype_atalkd,
 
256
                                    "as_timer configured %s phase 2 from seed",
 
257
                                    iface->i_name );
 
258
                        }
 
259
 
 
260
                        if ( looproute( iface, RTMP_ADD )) { /* -1 or 1 */
 
261
                            LOG(log_error, logtype_atalkd,
 
262
                                    "as_timer: can't route %u.%u to loop: %s",
 
263
                                    ntohs( iface->i_addr.sat_addr.s_net ),
 
264
                                    iface->i_addr.sat_addr.s_node,
 
265
                                    strerror(errno) );
 
266
                            atalkd_exit( 1 );
 
267
                        }
 
268
                        if ( iface == ciface ) {
 
269
                            ciface = ciface->i_next;
 
270
                            bootaddr( ciface );
 
271
                        }
 
272
                    }
 
273
                } else {
 
274
                    /*
 
275
                     * Configure for no router operation.  Wait for a route
 
276
                     * to become available in rtmp_packet().
 
277
                     */
 
278
                    LOG(log_info, logtype_atalkd, "config for no router" );
 
279
                      
 
280
                    if ( iface->i_flags & IFACE_PHASE2 ) {
 
281
                        iface->i_rt->rt_firstnet = 0;
 
282
                        iface->i_rt->rt_lastnet = htons( STARTUP_LASTNET );
 
283
                        setaddr( iface, IFACE_PHASE2,
 
284
                                iface->i_addr.sat_addr.s_net,
 
285
                                iface->i_addr.sat_addr.s_node,
 
286
                                0, htons( STARTUP_LASTNET ));
 
287
                    }
 
288
                    if ( looproute( iface, RTMP_ADD ) ) { /* -1 or 1 */
 
289
                        LOG(log_error, logtype_atalkd,
 
290
                                "as_timer: can't route %u.%u to loopback: %s",
 
291
                                ntohs( iface->i_addr.sat_addr.s_net ),
 
292
                                iface->i_addr.sat_addr.s_node,
 
293
                                strerror(errno) );
 
294
                        atalkd_exit( 1 );
 
295
                    }
 
296
 
 
297
                    if ( iface == ciface ) {
 
298
                      ciface = ciface->i_next;
 
299
                      bootaddr( ciface );
 
300
                    }
 
301
                }
 
302
            }
 
303
        }
 
304
 
 
305
        for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
 
306
            if ( fgate ) {
 
307
                free( (caddr_t)fgate );
 
308
                fgate = NULL;
 
309
            }
 
310
 
 
311
            n = 0;
 
312
            data = packet + 1 + sizeof( struct ziphdr );
 
313
            end = packet + sizeof( packet );
 
314
 
 
315
            sat = gate->g_sat;
 
316
            sat.sat_port = zap->ap_port;
 
317
 
 
318
            /*
 
319
             * Perform timeouts on routers.  If we've only got one
 
320
             * interface, we'll use these timeouts to decide that
 
321
             * our zone has gone away.
 
322
             */
 
323
            if ( ++gate->g_state >= RTMPTAB_BAD ) {
 
324
                LOG(log_info, logtype_atalkd, "as_timer gateway %u.%u down",
 
325
                        ntohs( gate->g_sat.sat_addr.s_net ),
 
326
                        gate->g_sat.sat_addr.s_node );
 
327
                rtmp = gate->g_rt;
 
328
                while ( rtmp ) {
 
329
                    frtmp = rtmp->rt_next;
 
330
                    if ( rtmp->rt_hops == RTMPHOPS_POISON ||
 
331
                            rtmp->rt_iprev == 0 ) {
 
332
                        rtmp_free( rtmp );
 
333
                    } else {
 
334
                        rtmp->rt_hops = RTMPHOPS_POISON;
 
335
                        if ((cc = rtmp_replace( rtmp )) < 0) {
 
336
                          LOG(log_error, logtype_atalkd, "rtmp_replace: %s", strerror(errno));
 
337
                          atalkd_exit(1);
 
338
                        }
 
339
                        if (cc) {
 
340
                            gate->g_state = rtmp->rt_state = RTMPTAB_GOOD;
 
341
                        }
 
342
                    }
 
343
                    rtmp = frtmp;
 
344
                }
 
345
                if ( gate->g_rt == 0 ) {
 
346
                    if ( gate->g_prev == 0 ) {
 
347
                        gate->g_iface->i_gate = gate->g_next;
 
348
                    } else {
 
349
                        gate->g_prev->g_next = gate->g_next;
 
350
                    }
 
351
                    if ( gate->g_next != 0 ) {
 
352
                        gate->g_next->g_prev = gate->g_prev;
 
353
                    }
 
354
                    fgate = gate;       /* can't free here, just mark it */
 
355
                }
 
356
                /*
 
357
                 * If this is the last router on the only interface,
 
358
                 * reconfigure our netrange.  By marking the interface
 
359
                 * as having no router, we will notice when a router
 
360
                 * comes back up.
 
361
                 *
 
362
                 * XXX: actually, we always reconfigure an interface
 
363
                 * if we're not a seed router.
 
364
                 */
 
365
 
 
366
                if ( gate->g_iface->i_gate == 0 && 
 
367
                     ((iface->i_flags & IFACE_SEED) == 0)) {
 
368
                    gate->g_iface->i_flags |= IFACE_NOROUTER;
 
369
                    gate->g_iface->i_flags &= ~IFACE_CONFIG;
 
370
 
 
371
                    /* get rid of any zones associated with this iface */
 
372
                    if (gate->g_iface->i_rt->rt_zt) {
 
373
                      rtmp_delzonemap(gate->g_iface->i_rt);
 
374
                      gate->g_iface->i_rt->rt_flags &= ~RTMPTAB_HASZONES;
 
375
                    }
 
376
 
 
377
                    LOG(log_info, logtype_atalkd, "as_timer last gateway down" );
 
378
 
 
379
                    /* Set netrange to 0-fffe.  */
 
380
                    if ( gate->g_iface->i_flags & IFACE_PHASE2 ) {
 
381
                        gate->g_iface->i_rt->rt_firstnet = 0;
 
382
                        gate->g_iface->i_rt->rt_lastnet =
 
383
                                htons( STARTUP_LASTNET );
 
384
                        setaddr( iface, IFACE_PHASE2,
 
385
                                iface->i_addr.sat_addr.s_net,
 
386
                                iface->i_addr.sat_addr.s_node,
 
387
                                0, htons( STARTUP_LASTNET ));
 
388
                    }
 
389
                }
 
390
                continue;
 
391
            }
 
392
 
 
393
            /*
 
394
             * If we don't have a zone for our interface yet, ask for
 
395
             * it from any router (all routers) on the interface.
 
396
             */
 
397
            if (( iface->i_rt->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
 
398
                iface->i_rt->rt_flags |= RTMPTAB_ZIPQUERY;
 
399
                memcpy( data, &iface->i_rt->rt_firstnet, sizeof( u_short ));
 
400
                data += sizeof( u_short );
 
401
                n++;
 
402
            }
 
403
 
 
404
            rtmp = gate->g_rt;
 
405
            while ( rtmp ) {
 
406
                /*
 
407
                 * Delete old routing tuples.
 
408
                 */
 
409
                if ( rtmp->rt_state != RTMPTAB_PERM ) {
 
410
                    rtmp->rt_state++;
 
411
                }
 
412
 
 
413
                /*
 
414
                 * We've not been updated for this route in a while.  If
 
415
                 * it's not in use, go ahead and remove it.  If it is in
 
416
                 * use, mark the route as down (POISON), and look for a
 
417
                 * better route.  If one is found, delete this route and use
 
418
                 * the new one.  If it's not found, mark the route as GOOD
 
419
                 * (so we'll propogate our poison) and delete it the next
 
420
                 * time it becomes BAD.
 
421
                 */
 
422
                if ( rtmp->rt_state >= RTMPTAB_BAD ) {
 
423
                    frtmp = rtmp->rt_next;
 
424
                    if ( rtmp->rt_iprev == 0 ) {        /* not in use */
 
425
                        rtmp_free( rtmp );
 
426
                    } else {                            /* in use */
 
427
                        if ( rtmp->rt_hops == RTMPHOPS_POISON ) {
 
428
                            rtmp_free( rtmp );
 
429
                        } else {
 
430
                            rtmp->rt_hops = RTMPHOPS_POISON;
 
431
                            if ((cc = rtmp_replace( rtmp )) < 0) {
 
432
                                LOG(log_error, logtype_atalkd, "rtmp_replace: %s", strerror(errno));
 
433
                                atalkd_exit(1);
 
434
                            }
 
435
                            if (cc)
 
436
                                rtmp->rt_state = RTMPTAB_GOOD;
 
437
                        }
 
438
                    }
 
439
                    rtmp = frtmp;
 
440
                    continue;
 
441
                }
 
442
 
 
443
                /*
 
444
                 * Do ZIP lookups.
 
445
                 */
 
446
                if ( rtmp->rt_iprev &&
 
447
                        ( rtmp->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
 
448
                    if ( data + sizeof( u_short ) > end || n == 255 ) {
 
449
                        /* send what we've got */
 
450
                        zh.zh_op = ZIPOP_QUERY;
 
451
                        zh.zh_count = n;
 
452
                        cc = data - packet;
 
453
                        data = packet;
 
454
                        *data++ = DDPTYPE_ZIP;
 
455
                        memcpy( data, &zh, sizeof( struct ziphdr ));
 
456
 
 
457
                        if ( sendto( zap->ap_fd, packet, cc, 0,
 
458
                                (struct sockaddr *)&sat,
 
459
                                sizeof( struct sockaddr_at )) < 0 ) {
 
460
                            LOG(log_error, logtype_atalkd, "as_timer sendto: %s", strerror(errno) );
 
461
                        }
 
462
                        sentzipq = 1;
 
463
 
 
464
                        n = 0;
 
465
                        data = packet + 1 + sizeof( struct ziphdr );
 
466
                        end = packet + sizeof( packet );
 
467
                    }
 
468
 
 
469
                    /*
 
470
                     * rt_nzq is number of ZIP Queries we've issued for a
 
471
                     * given netrange.  If we've got ziptimeout on, we
 
472
                     * will only ask 3 times for any given netrange.
 
473
                     * Interestingly enough, since rt_nzq is a u_char,
 
474
                     * it will overflow after a while.  This means we will
 
475
                     * periodically ask for nets that we've decided not to
 
476
                     * ask about, and warn that we can't get it's zone.
 
477
                     */
 
478
                    if ( rtmp->rt_nzq++ == 3 ) {
 
479
                        LOG(log_info, logtype_atalkd, "as_timer can't get zone for %u",
 
480
                                ntohs( rtmp->rt_firstnet ));
 
481
                    }
 
482
                    if ( rtmp->rt_nzq > 3 ) {
 
483
                        if ( ziptimeout ) {
 
484
                            rtmp = rtmp->rt_next;
 
485
                            continue;
 
486
                        }
 
487
                    } else {
 
488
                        sentzipq = 1;
 
489
                    }
 
490
                    rtmp->rt_flags |= RTMPTAB_ZIPQUERY;
 
491
                    memcpy( data, &rtmp->rt_firstnet, sizeof( u_short ));
 
492
                    data += sizeof( u_short );
 
493
                    n++;
 
494
                }
 
495
                rtmp = rtmp->rt_next;
 
496
            }
 
497
 
 
498
            /* send what we've got */
 
499
            if ( n > 0 ) {
 
500
                zh.zh_op = ZIPOP_QUERY;
 
501
                zh.zh_count = n;
 
502
                cc = data - packet;
 
503
                data = packet;
 
504
                *data++ = DDPTYPE_ZIP;
 
505
                memcpy( data, &zh, sizeof( struct ziphdr ));
 
506
 
 
507
                if ( sendto( zap->ap_fd, packet, cc, 0, (struct sockaddr *)&sat,
 
508
                        sizeof( struct sockaddr_at )) < 0 ) {
 
509
                    LOG(log_error, logtype_atalkd, "as_timer sendto: %s", strerror(errno) );
 
510
                }
 
511
            }
 
512
        }
 
513
        if ( fgate ) {
 
514
            free( (caddr_t)fgate );
 
515
            fgate = NULL;
 
516
        }
 
517
 
 
518
        /*
 
519
         * Send RTMP broadcasts if we have multiple interfaces or our 
 
520
         * interface is configured as a router.  
 
521
         */
 
522
        if ((iface->i_flags & IFACE_ISROUTER)) {
 
523
#ifdef BSD4_4
 
524
            sat.sat_len = sizeof( struct sockaddr_at );
 
525
#endif /* BSD4_4 */
 
526
            sat.sat_family = AF_APPLETALK;
 
527
            sat.sat_addr.s_net = ATADDR_ANYNET;
 
528
            sat.sat_addr.s_node = ATADDR_BCAST;
 
529
            sat.sat_port = rap->ap_port;
 
530
 
 
531
            data = packet;
 
532
            end = data + sizeof( packet );
 
533
            *data++ = DDPTYPE_RTMPRD;
 
534
            rh.rh_net = iface->i_addr.sat_addr.s_net;
 
535
            rh.rh_nodelen = 8;
 
536
            rh.rh_node = iface->i_addr.sat_addr.s_node;
 
537
            memcpy( data, &rh, sizeof( struct rtmp_head ));
 
538
            data += sizeof( struct rtmp_head );
 
539
            n = 0;
 
540
 
 
541
 
 
542
            if ( iface->i_flags & IFACE_PHASE1 ) {
 
543
                rt.rt_net = 0;
 
544
                rt.rt_dist = 0x82;
 
545
                memcpy( data, &rt, SZ_RTMPTUPLE );
 
546
                data += SZ_RTMPTUPLE;
 
547
            } else {
 
548
                rt.rt_net = iface->i_rt->rt_firstnet;
 
549
                rt.rt_dist = 0x80;
 
550
                memcpy( data, &rt, SZ_RTMPTUPLE );
 
551
                data += SZ_RTMPTUPLE;
 
552
 
 
553
                rt.rt_net = iface->i_rt->rt_lastnet;
 
554
                rt.rt_dist = 0x82;
 
555
                memcpy( data, &rt, SZ_RTMPTUPLE );
 
556
                data += SZ_RTMPTUPLE;
 
557
            }
 
558
 
 
559
            for ( iface2 = interfaces; iface2; iface2 = iface2->i_next ) {
 
560
 
 
561
              /* XXX: there used to be a bit checking against iface ==
 
562
                 iface2. also, we don't want to send an rtmp broadcast
 
563
                 to an interface that doesn't want it.  */
 
564
                if ((( iface2->i_flags & IFACE_CONFIG ) == 0) ||
 
565
                    ((iface2->i_flags & IFACE_ISROUTER) == 0)) {
 
566
                    continue;
 
567
                }
 
568
                /*
 
569
                 * Fill in tuples.  Always send the same thing, regardless
 
570
                 * of the phase of the destination.  Routers who don't
 
571
                 * understand extended rtmp packets will toss extended
 
572
                 * tuples because their distance will have the high bit set.
 
573
                 */
 
574
                for ( rtmp = iface2->i_rt; rtmp; rtmp = rtmp->rt_inext ) {
 
575
                    /* don't broadcast routes we have no zone for */
 
576
                    if ( rtmp->rt_zt == 0 ||
 
577
                            ( rtmp->rt_flags & RTMPTAB_ZIPQUERY ) ||
 
578
                            ( rtmp->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
 
579
                        continue;
 
580
                    }
 
581
 
 
582
                    if ((( rtmp->rt_flags & RTMPTAB_EXTENDED ) &&
 
583
                            data + 2 * SZ_RTMPTUPLE > end ) ||
 
584
                            data + SZ_RTMPTUPLE > end ) {
 
585
                        if ( sendto( rap->ap_fd, packet, data - packet, 0,
 
586
                                (struct sockaddr *)&sat,
 
587
                                sizeof( struct sockaddr_at )) < 0 ) {
 
588
                            LOG(log_error, logtype_atalkd, "as_timer sendto %u.%u (%u): %s",
 
589
                                    ntohs( sat.sat_addr.s_net ),
 
590
                                    sat.sat_addr.s_node,
 
591
                                    ntohs( iface->i_rt->rt_firstnet ),
 
592
                                    strerror(errno) );
 
593
                        }
 
594
 
 
595
                        if ( iface->i_flags & IFACE_PHASE2 ) {
 
596
                            data = packet + 1 + sizeof( struct rtmp_head ) +
 
597
                                    2 * SZ_RTMPTUPLE;
 
598
                        } else {
 
599
                            data = packet + 1 + sizeof( struct rtmp_head ) +
 
600
                                    SZ_RTMPTUPLE;
 
601
                        }
 
602
                        n = 0;
 
603
                    }
 
604
 
 
605
                    rt.rt_net = rtmp->rt_firstnet;
 
606
                    rt.rt_dist = rtmp->rt_hops;
 
607
                    if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
 
608
                        rt.rt_dist |= 0x80;
 
609
                    }
 
610
                    memcpy( data, &rt, SZ_RTMPTUPLE );
 
611
                    data += SZ_RTMPTUPLE;
 
612
 
 
613
                    if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
 
614
                        rt.rt_net = rtmp->rt_lastnet;
 
615
                        rt.rt_dist = 0x82;
 
616
                        memcpy( data, &rt, SZ_RTMPTUPLE );
 
617
                        data += SZ_RTMPTUPLE;
 
618
                    }
 
619
                    n++;
 
620
                }
 
621
            }
 
622
 
 
623
            /* send rest */
 
624
            if ( n ) {
 
625
                if ( sendto( rap->ap_fd, packet, data - packet, 0,
 
626
                        (struct sockaddr *)&sat,
 
627
                        sizeof( struct sockaddr_at )) < 0 ) {
 
628
                    LOG(log_error, logtype_atalkd, "as_timer sendto %u.%u (%u): %s",
 
629
                            ntohs( sat.sat_addr.s_net ),
 
630
                            sat.sat_addr.s_node,
 
631
                            ntohs( iface->i_rt->rt_firstnet ),
 
632
                            strerror(errno) );
 
633
                }
 
634
            }
 
635
        }
 
636
    }
 
637
 
 
638
    /*
 
639
     * Check if we're stable.  Each time we configure an interface, we
 
640
     * sent stabletimer to UNSTABLE.  If stabletimer ever gets to
 
641
     * STABLEANYWAY, we give up and decide to "be" stable anyway.
 
642
     * Normally, we wait for stabletimer get <= STABLE with no new rtmp
 
643
     * data and all zip data complete.
 
644
     */
 
645
    if ( !stable ) {
 
646
        if ( stabletimer <= STABLE && !newrtmpdata && !sentzipq ) {
 
647
            /* write out config file */
 
648
            stable = 1;
 
649
            writeconf( configfile );
 
650
        } else {
 
651
            if ( stabletimer-- <= STABLEANYWAY ) {
 
652
                stable = 1;
 
653
            }
 
654
        }
 
655
        newrtmpdata = 0;
 
656
 
 
657
        if ( stable && !noparent ) {
 
658
            noparent = 1;
 
659
            LOG(log_info, logtype_atalkd, "ready %d/%d/%d", stabletimer, newrtmpdata,
 
660
                    sentzipq );
 
661
            if ( !debug ) {
 
662
                /*
 
663
                 * Seems like we could get here more than once...
 
664
                 */
 
665
                if ( kill( getpid(), SIGSTOP ) < 0 ) {
 
666
                    LOG(log_error, logtype_atalkd, "as_timer: kill-self failed!" );
 
667
                    atalkd_exit( 1 );
 
668
                }
 
669
            }
 
670
        }
 
671
    }
 
672
 
 
673
#ifdef DEBUG
 
674
    consistency();
 
675
#endif /* DEBUG */
 
676
}
 
677
 
 
678
#ifdef DEBUG
 
679
/*
 
680
* Consistency check...
 
681
*/
 
682
consistency()
 
683
{
 
684
    struct rtmptab      *rtmp;
 
685
    struct list         *lr, *lz;
 
686
    struct ziptab       *zt;
 
687
 
 
688
    for ( zt = ziptab; zt; zt = zt->zt_next ) {
 
689
        for ( lr = zt->zt_rt; lr; lr = lr->l_next ) {
 
690
            rtmp = (struct rtmptab *)lr->l_data;
 
691
            if ( rtmp->rt_iprev == 0 && rtmp->rt_gate != 0 ) {
 
692
                LOG(log_error, logtype_atalkd, "%.*s has %u-%u (unused)\n",
 
693
                        zt->zt_len, zt->zt_name, ntohs( rtmp->rt_firstnet ),
 
694
                        ntohs( rtmp->rt_lastnet ));
 
695
                atalkd_exit(1);
 
696
            }
 
697
            for ( lz = rtmp->rt_zt; lz; lz = lz->l_next ) {
 
698
                if ( zt == (struct ziptab *)lz->l_data ) {
 
699
                    break;
 
700
                }
 
701
            }
 
702
            if ( lz == 0 ) {
 
703
                LOG(log_error, logtype_atalkd, "no map from %u-%u to %.*s\n", 
 
704
                        ntohs( rtmp->rt_firstnet ),
 
705
                        ntohs( rtmp->rt_lastnet ),
 
706
                        zt->zt_len, zt->zt_name );
 
707
                atalkd_exit(1);
 
708
            }
 
709
        }
 
710
    }
 
711
}
 
712
#endif /* DEBUG */
 
713
 
 
714
#if !defined( ibm032 ) && !defined( _IBMR2 )
 
715
    void
 
716
#endif /* ! ibm032 && ! _IBMR2 */
 
717
as_debug()
 
718
{
 
719
    struct interface    *iface;
 
720
    struct list         *l;
 
721
    struct ziptab       *zt;
 
722
    struct gate         *gate;
 
723
    struct rtmptab      *rt;
 
724
    FILE                *rtmpdebug;
 
725
 
 
726
    if (( rtmpdebug = fopen( _PATH_ATALKDEBUG, "w" )) == NULL ) {
 
727
        LOG(log_error, logtype_atalkd, "rtmp: %s", strerror(errno) );
 
728
    }
 
729
 
 
730
    for ( iface = interfaces; iface; iface = iface->i_next ) {
 
731
        fprintf( rtmpdebug, "interface %s %u.%u ", iface->i_name,
 
732
                ntohs( iface->i_addr.sat_addr.s_net ),
 
733
                iface->i_addr.sat_addr.s_node );
 
734
        if ( iface->i_flags & IFACE_PHASE1 ) {
 
735
            putc( '1', rtmpdebug );
 
736
        }
 
737
        if ( iface->i_flags & IFACE_PHASE2 ) {
 
738
            putc( '2', rtmpdebug );
 
739
        }
 
740
        if ( iface->i_flags & IFACE_RSEED ) {
 
741
            putc( 'R', rtmpdebug );
 
742
        }
 
743
        if ( iface->i_flags & IFACE_SEED ) {
 
744
            putc( 'S', rtmpdebug );
 
745
        }
 
746
        if ( iface->i_flags & IFACE_DONTROUTE ) {
 
747
            putc( 'D', rtmpdebug );
 
748
        }
 
749
        if ( iface->i_flags & IFACE_ADDR ) {
 
750
            putc( 'A', rtmpdebug );
 
751
        }
 
752
        if ( iface->i_flags & IFACE_CONFIG ) {
 
753
            putc( 'C', rtmpdebug );
 
754
        }
 
755
        if ( iface->i_flags & IFACE_NOROUTER ) {
 
756
            putc( 'N', rtmpdebug );
 
757
        }
 
758
        if ( iface->i_flags & IFACE_LOOP ) {
 
759
            putc( 'L', rtmpdebug );
 
760
        }
 
761
        putc( '\n', rtmpdebug );
 
762
 
 
763
        if ( iface->i_rt ) {
 
764
            fprintf( rtmpdebug, "\t%u-%u ",
 
765
                    ntohs( iface->i_rt->rt_firstnet ),
 
766
                    ntohs( iface->i_rt->rt_lastnet ));
 
767
            if ( iface->i_rt->rt_flags & RTMPTAB_ZIPQUERY ) {
 
768
                putc( 'q', rtmpdebug );
 
769
            }
 
770
            if ( iface->i_rt->rt_flags & RTMPTAB_HASZONES ) {
 
771
                putc( 'z', rtmpdebug );
 
772
            }
 
773
            if ( iface->i_rt->rt_flags & RTMPTAB_EXTENDED ) {
 
774
                putc( 'x', rtmpdebug );
 
775
            }
 
776
            putc( 'i', rtmpdebug );
 
777
            for ( l = iface->i_rt->rt_zt; l; l = l->l_next ) {
 
778
                zt = (struct ziptab *)l->l_data;
 
779
                fprintf( rtmpdebug, " '%.*s'", zt->zt_len, zt->zt_name );
 
780
            }
 
781
            fprintf( rtmpdebug, "\n" );
 
782
        }
 
783
 
 
784
        for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
 
785
            fprintf( rtmpdebug, "gate %u.%u %X\n",
 
786
                    ntohs( gate->g_sat.sat_addr.s_net ),
 
787
                    gate->g_sat.sat_addr.s_node, gate->g_state );
 
788
            for ( rt = gate->g_rt; rt; rt = rt->rt_next ) {
 
789
                fprintf( rtmpdebug, "\t%u-%u ", ntohs( rt->rt_firstnet ),
 
790
                        ntohs( rt->rt_lastnet ));
 
791
                if ( rt->rt_flags & RTMPTAB_ZIPQUERY ) {
 
792
                    putc( 'q', rtmpdebug );
 
793
                }
 
794
                if ( rt->rt_flags & RTMPTAB_HASZONES ) {
 
795
                    putc( 'z', rtmpdebug );
 
796
                }
 
797
                if ( rt->rt_flags & RTMPTAB_EXTENDED ) {
 
798
                    putc( 'x', rtmpdebug );
 
799
                }
 
800
                if ( rt->rt_iprev ) {
 
801
                    putc( 'i', rtmpdebug );
 
802
                }
 
803
                for ( l = rt->rt_zt; l; l = l->l_next ) {
 
804
                    zt = (struct ziptab *)l->l_data;
 
805
                    fprintf( rtmpdebug, " '%.*s'", zt->zt_len, zt->zt_name );
 
806
                }
 
807
                fprintf( rtmpdebug, "\n" );
 
808
            }
 
809
        }
 
810
    }
 
811
 
 
812
    fclose( rtmpdebug );
 
813
}
 
814
 
 
815
/*
 
816
 * Called when SIGTERM is recieved.  Remove all routes and then exit.
 
817
 */
 
818
#if !defined( ibm032 ) && !defined( _IBMR2 )
 
819
    void
 
820
#endif /* ! ibm032 && ! _IBMR2 */
 
821
as_down()
 
822
{
 
823
    struct interface    *iface;
 
824
    struct gate         *gate;
 
825
    struct rtmptab      *rt;
 
826
 
 
827
    for ( iface = interfaces; iface; iface = iface->i_next ) {
 
828
        for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
 
829
            for ( rt = gate->g_rt; rt; rt = rt->rt_next ) {
 
830
                if ( rt->rt_iprev ) {
 
831
                    if ( gateroute( RTMP_DEL, rt ) < 0 ) {
 
832
                        LOG(log_error, logtype_atalkd, "as_down remove %u-%u failed: %s",
 
833
                                ntohs( rt->rt_firstnet ),
 
834
                                ntohs( rt->rt_lastnet ),
 
835
                                strerror(errno) );
 
836
                    }
 
837
                }
 
838
            }
 
839
        }
 
840
        if ( iface->i_flags & IFACE_LOOP ) {
 
841
          if (looproute( iface, RTMP_DEL )) {
 
842
            LOG(log_error, logtype_atalkd, "as_down remove %s %u.%u failed: %s",
 
843
                    iface->i_name, ntohs( iface->i_addr.sat_addr.s_net ),
 
844
                    iface->i_addr.sat_addr.s_node,
 
845
                    strerror(errno) );
 
846
          }
 
847
        }
 
848
    }
 
849
 
 
850
    LOG(log_info, logtype_atalkd, "done" );
 
851
    atalkd_exit( 0 );
 
852
}
 
853
 
 
854
int main( ac, av )
 
855
    int         ac;
 
856
    char        **av;
 
857
{
 
858
    extern char         *optarg;
 
859
    extern int          optind;
 
860
 
 
861
    struct sockaddr_at  sat;
 
862
    struct sigaction    sv;
 
863
    struct itimerval    it;
 
864
    struct interface    *iface;
 
865
    int                 status;
 
866
    struct atport       *ap;
 
867
    fd_set              readfds;
 
868
    int                 i, mask, c;
 
869
    SOCKLEN_T           fromlen;
 
870
    char                *prog;
 
871
;
 
872
 
 
873
    while (( c = getopt( ac, av, "12qsdtf:P:v" )) != EOF ) {
 
874
        switch ( c ) {
 
875
        case '1' :
 
876
            defphase = IFACE_PHASE1;
 
877
            break;
 
878
 
 
879
        case '2' :
 
880
            defphase = IFACE_PHASE2;
 
881
            break;
 
882
 
 
883
        case 'd' :
 
884
            debug++;
 
885
            break;
 
886
 
 
887
        case 'f' :
 
888
            configfile = optarg;
 
889
            break;
 
890
 
 
891
        case 'q' :      /* don't seed */
 
892
            quiet++;
 
893
            break;
 
894
 
 
895
        case 's' :      /* seed */
 
896
            chatty++;
 
897
            break;
 
898
 
 
899
        case 't' :      /* transition */
 
900
            transition++;
 
901
            break;
 
902
 
 
903
        case 'P' :      /* pid file */
 
904
            pidfile = optarg;
 
905
            break;
 
906
 
 
907
        case 'v' :      /* version */
 
908
            printf( "atalkd (version %s)\n", version );
 
909
            exit ( 1 );
 
910
            break;
 
911
 
 
912
        default :
 
913
            fprintf( stderr, "Unknown option -- '%c'\n", c );
 
914
            exit( 1 );
 
915
        }
 
916
    }
 
917
    if ( optind != ac ) {
 
918
        fprintf( stderr, "Too many arguments.\n" );
 
919
        exit( 1 );
 
920
    }
 
921
 
 
922
    if (( prog = strrchr( av[ 0 ], '/' )) == NULL ) {
 
923
        prog = av[ 0 ];
 
924
    } else {
 
925
        prog++;
 
926
    }
 
927
 
 
928
    /*
 
929
     * Configure loop back address first, so appearances of "lo0" in
 
930
     * the config file fail.  Also insures that lo0 gets configured,
 
931
     * even if there's some hangup during configuration of some
 
932
     * other interface.
 
933
     */
 
934
    if (( interfaces = newiface( LOOPIFACE )) == NULL ) {
 
935
        perror( "newiface" );
 
936
        exit( 1 );
 
937
    }
 
938
    interfaces->i_flags |= IFACE_PHASE2 | IFACE_LOOPBACK;
 
939
 
 
940
    /*
 
941
     * Check our initial configuration before we fork. This way we can
 
942
     * complain about syntax errors on stdout.
 
943
     *
 
944
     * Basically, if we're going to read our config file, we should read
 
945
     * it and initialize our data structures. If we're not going to read
 
946
     * our config file, use GIFCONF to initialize our data structures.
 
947
     */
 
948
    if ( readconf( configfile ) < 0 && getifconf() < 0 ) {
 
949
        fprintf( stderr, "%s: can't get interfaces, exiting.\n", prog );
 
950
        exit( 1 );
 
951
    }
 
952
 
 
953
    /* we need to count up our interfaces so that we can simplify things
 
954
     * later. we also need to figure out if we have more than one interface
 
955
     * that is routing. */
 
956
    for (i = 0, ninterfaces = 0, iface = interfaces; iface;
 
957
         iface=iface->i_next) {
 
958
      if (iface->i_flags & IFACE_DONTROUTE)
 
959
        i++;
 
960
      ninterfaces++;
 
961
    }
 
962
    i = ninterfaces - i; /* number of routable interfaces */
 
963
 
 
964
    /*
 
965
     * At this point, we have (at least partially) initialized data
 
966
     * structures. Fill in what we can and verify that nothing is obviously
 
967
     * broken.
 
968
     */
 
969
    for (iface = interfaces; iface; iface = iface->i_next) {
 
970
        /* Apply the default phase */
 
971
        if (( iface->i_flags & IFACE_PHASE1 ) == 0 &&
 
972
                ( iface->i_flags & IFACE_PHASE2 ) == 0 ) {
 
973
            iface->i_flags |= defphase;
 
974
        }
 
975
 
 
976
        /* set up router flag information. if we have multiple interfaces
 
977
         * and DONTROUTE isn't set, set up ROUTER. i is the number of 
 
978
         * interfaces that don't have the DONTROUTE flag set. */
 
979
        if ((i > IFBASE) && ((iface->i_flags & IFACE_DONTROUTE) == 0)) {
 
980
          iface->i_flags |= IFACE_ISROUTER;
 
981
        }
 
982
 
 
983
        /* Set default addresses */
 
984
        if ( iface->i_rt == NULL ) {
 
985
            if (( iface->i_rt = newrt(iface)) == NULL ) {
 
986
                perror( "newrt" );
 
987
                exit( 1 );
 
988
            }
 
989
 
 
990
            if ( iface->i_flags & IFACE_PHASE1 ) {
 
991
                iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet =
 
992
                        iface->i_caddr.sat_addr.s_net;
 
993
            } else {
 
994
                if ( iface->i_caddr.sat_addr.s_net != ATADDR_ANYNET ||
 
995
                        ( iface->i_flags & IFACE_LOOPBACK )) {
 
996
                    iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet =
 
997
                            iface->i_caddr.sat_addr.s_net;
 
998
                } else {
 
999
                    iface->i_rt->rt_firstnet = htons( STARTUP_FIRSTNET );
 
1000
                    iface->i_rt->rt_lastnet = htons( STARTUP_LASTNET );
 
1001
                }
 
1002
            }
 
1003
        }
 
1004
        
 
1005
        if (( iface->i_flags & IFACE_PHASE1 ) == 0 ) {
 
1006
            iface->i_rt->rt_flags |= RTMPTAB_EXTENDED;
 
1007
        }
 
1008
 
 
1009
        if ( iface->i_caddr.sat_addr.s_net == ATADDR_ANYNET ) {
 
1010
            iface->i_caddr.sat_addr.s_net = iface->i_rt->rt_firstnet;
 
1011
        }
 
1012
 
 
1013
        if ( debug ) {
 
1014
            dumpconfig( iface );        /* probably needs args */
 
1015
        }
 
1016
    }
 
1017
 
 
1018
    /*
 
1019
     * A little consistency check...
 
1020
     */
 
1021
    if ( ninterfaces < IFBASE ) {
 
1022
        fprintf( stderr, "%s: zero interfaces, exiting.\n", prog );
 
1023
        exit( 1 );
 
1024
    }
 
1025
 
 
1026
    /* do this here so that we can use ifconfig */
 
1027
#ifdef __svr4__
 
1028
    if ( plumb() < 0 ) {
 
1029
        fprintf(stderr, "can't establish STREAMS plumbing, exiting.\n" );
 
1030
        atalkd_exit( 1 );
 
1031
    }
 
1032
#endif /* __svr4__ */
 
1033
 
 
1034
    /* delete pre-existing interface addresses. */
 
1035
#ifdef SIOCDIFADDR
 
1036
    for (iface = interfaces; iface; iface = iface->i_next) {
 
1037
      if (ifconfig(iface->i_name, SIOCDIFADDR, &iface->i_addr)) {
 
1038
#ifdef SIOCATALKDIFADDR
 
1039
#if (SIOCDIFADDR != SIOCATALKDIFADDR)
 
1040
        ifconfig(iface->i_name, SIOCATALKDIFADDR, &iface->i_addr);
 
1041
#endif /* SIOCDIFADDR != SIOCATALKDIFADDR */
 
1042
#endif /* SIOCATALKDIFADDR */
 
1043
      }
 
1044
    }
 
1045
#endif /* SIOCDIFADDR */
 
1046
 
 
1047
    /*
 
1048
     * Disassociate. The child will send itself a signal when it is
 
1049
     * stable. This indicates that other processes may begin using
 
1050
     * AppleTalk.
 
1051
     */
 
1052
    switch (i = server_lock("atalkd", pidfile, debug)) {
 
1053
    case -1:
 
1054
      exit(1);
 
1055
    case 0: /* child */
 
1056
      break;
 
1057
    default: /* parent */
 
1058
      /*
 
1059
       * Wait for the child to send itself a SIGSTOP, after which
 
1060
       * we send it a SIGCONT and exit ourself.
 
1061
       */
 
1062
      if ( wait3( &status, WUNTRACED, (struct rusage *)0 ) != i) {
 
1063
        perror( "wait3" );      /* Child died? */
 
1064
        atalkd_exit( 1 );
 
1065
      }
 
1066
      if ( !WIFSTOPPED( status )) {
 
1067
        fprintf( stderr, "AppleTalk not up! Check your syslog for the reason." );
 
1068
        if ( WIFEXITED( status )) {
 
1069
          fprintf( stderr, " Child exited with %d.\n",
 
1070
                   WEXITSTATUS( status ));
 
1071
        } else {
 
1072
          fprintf( stderr, " Child died.\n" );
 
1073
        }
 
1074
        atalkd_exit( 1 );
 
1075
      }
 
1076
      if ( kill(i, SIGCONT ) < 0 ) {
 
1077
        perror( "kill" );
 
1078
        atalkd_exit( 1 );
 
1079
      }
 
1080
      exit( 0 );
 
1081
    }
 
1082
 
 
1083
#ifdef ultrix
 
1084
    openlog( prog, LOG_PID );
 
1085
#else /* ultrix */
 
1086
    set_processname(prog);
 
1087
    syslog_setup(log_debug, logtype_default, logoption_pid, logfacility_daemon );
 
1088
#endif /* ultrix */
 
1089
 
 
1090
    LOG(log_info, logtype_atalkd, "restart (%s)", version );
 
1091
 
 
1092
    /*
 
1093
     * Socket for use in routing ioctl()s. Can't add routes to our
 
1094
     * interfaces until we have our routing socket.
 
1095
     */
 
1096
#ifdef BSD4_4
 
1097
    if (( rtfd = socket( PF_ROUTE, SOCK_RAW, AF_APPLETALK )) < 0 ) {
 
1098
        LOG(log_error, logtype_atalkd, "route socket: %s", strerror(errno) );
 
1099
        atalkd_exit( 1 );
 
1100
    }
 
1101
    if ( shutdown( rtfd, 0 ) < 0 ) {
 
1102
        LOG(log_error, logtype_atalkd, "route shutdown: %s", strerror(errno) );
 
1103
        atalkd_exit( 1 );
 
1104
    }
 
1105
#else /* BSD4_4 */
 
1106
    if (( rtfd = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
 
1107
        LOG(log_error, logtype_atalkd, "route socket: %s", strerror(errno) );
 
1108
        atalkd_exit( 1 );
 
1109
    }
 
1110
#endif /* BSD4_4 */
 
1111
 
 
1112
    ciface = interfaces;
 
1113
    bootaddr( ciface );
 
1114
 
 
1115
    memset(&sv, 0, sizeof(sv));
 
1116
    sv.sa_handler = as_down;
 
1117
    sigemptyset( &sv.sa_mask );
 
1118
    sigaddset( &sv.sa_mask, SIGUSR1 );
 
1119
    sigaddset( &sv.sa_mask, SIGALRM );
 
1120
    sigaddset( &sv.sa_mask, SIGTERM );
 
1121
    sv.sa_flags = SA_RESTART;
 
1122
    if ( sigaction( SIGTERM, &sv, NULL) < 0 ) {
 
1123
        LOG(log_error, logtype_atalkd, "sigterm: %s", strerror(errno) );
 
1124
        atalkd_exit( 1 );
 
1125
    }
 
1126
 
 
1127
    sv.sa_handler = as_debug;
 
1128
    sigemptyset( &sv.sa_mask );
 
1129
    sigaddset( &sv.sa_mask, SIGUSR1 );
 
1130
    sigaddset( &sv.sa_mask, SIGALRM );
 
1131
    sigaddset( &sv.sa_mask, SIGTERM );
 
1132
    sv.sa_flags = SA_RESTART;
 
1133
    if ( sigaction( SIGUSR1, &sv, NULL) < 0 ) {
 
1134
        LOG(log_error, logtype_atalkd, "sigusr1: %s", strerror(errno) );
 
1135
        atalkd_exit( 1 );
 
1136
    }
 
1137
 
 
1138
    sv.sa_handler = as_timer;
 
1139
    sigemptyset( &sv.sa_mask );
 
1140
    sigaddset( &sv.sa_mask, SIGUSR1 );
 
1141
    sigaddset( &sv.sa_mask, SIGALRM );
 
1142
    sigaddset( &sv.sa_mask, SIGTERM );
 
1143
    sv.sa_flags = SA_RESTART;
 
1144
    if ( sigaction( SIGALRM, &sv, NULL) < 0 ) {
 
1145
        LOG(log_error, logtype_atalkd, "sigalrm: %s", strerror(errno) );
 
1146
        atalkd_exit( 1 );
 
1147
    }
 
1148
 
 
1149
    it.it_interval.tv_sec = 10L;
 
1150
    it.it_interval.tv_usec = 0L;
 
1151
    it.it_value.tv_sec = 10L;
 
1152
    it.it_value.tv_usec = 0L;
 
1153
    if ( setitimer( ITIMER_REAL, &it, NULL) < 0 ) {
 
1154
        LOG(log_error, logtype_atalkd, "setitimer: %s", strerror(errno) );
 
1155
        atalkd_exit( 1 );
 
1156
    }
 
1157
 
 
1158
    for (;;) {
 
1159
        readfds = fds;
 
1160
        if ( select( nfds, &readfds, NULL, NULL, NULL) < 0 ) {
 
1161
            if ( errno == EINTR ) {
 
1162
                errno = 0;
 
1163
                continue;
 
1164
            } else {
 
1165
                LOG(log_error, logtype_atalkd, "select: %s", strerror(errno) );
 
1166
                atalkd_exit( 1 );
 
1167
            }
 
1168
        }
 
1169
 
 
1170
        for ( iface = interfaces; iface; iface = iface->i_next ) {
 
1171
            for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
 
1172
                if ( FD_ISSET( ap->ap_fd, &readfds )) {
 
1173
                    if ( ap->ap_packet ) {
 
1174
                        fromlen = sizeof( struct sockaddr_at );
 
1175
                        if (( c = recvfrom( ap->ap_fd, Packet, sizeof( Packet ),
 
1176
                                0, (struct sockaddr *)&sat, &fromlen )) < 0 ) {
 
1177
                            LOG(log_error, logtype_atalkd, "recvfrom: %s", strerror(errno) );
 
1178
                            continue;
 
1179
                        }
 
1180
#ifdef DEBUG
 
1181
                        if ( debug ) {
 
1182
                            printf( "packet from %u.%u on %s (%x) %d (%d)\n",
 
1183
                                    ntohs( sat.sat_addr.s_net ),
 
1184
                                    sat.sat_addr.s_node, iface->i_name,
 
1185
                                    iface->i_flags, ap->ap_port, ap->ap_fd );
 
1186
                            bprint( Packet, c );
 
1187
                        }
 
1188
#endif /* DEBUG */
 
1189
#ifdef __svr4__
 
1190
                        if ( sighold( SIGALRM ) || sighold( SIGUSR1 )) {
 
1191
                            LOG(log_error, logtype_atalkd, "sighold: %s", strerror(errno) );
 
1192
                            atalkd_exit( 1 );
 
1193
                        }
 
1194
#else /* __svr4__ */
 
1195
                        mask = sigsetmask( sigmask( SIGALRM ) |
 
1196
                                sigmask( SIGUSR1 ));
 
1197
#endif /* __svr4__ */
 
1198
                        if (( *ap->ap_packet )( ap, &sat, Packet, c ) < 0) {
 
1199
                          LOG(log_error, logtype_atalkd, "ap->ap_packet: %s", strerror(errno));
 
1200
                          atalkd_exit(1);
 
1201
                        }
 
1202
 
 
1203
#ifdef DEBUG
 
1204
                        consistency();
 
1205
#endif /* DEBUG */
 
1206
#ifdef __svr4__
 
1207
                        if ( sigrelse( SIGUSR1 ) || sigrelse( SIGALRM )) {
 
1208
                            LOG(log_error, logtype_atalkd, "sigrelse: %s", strerror(errno) );
 
1209
                            atalkd_exit( 1 );
 
1210
                        }
 
1211
#else /* __svr4__ */
 
1212
                        sigsetmask( mask );
 
1213
#endif /* __svr4__ */
 
1214
                    }
 
1215
                }
 
1216
            }
 
1217
        }
 
1218
    }
 
1219
}
 
1220
 
 
1221
/*
 
1222
 * This code is called (from main(), as_timer(), zip_packet(),
 
1223
 * and rtmp_packet()) to set the initial "bootstrapping" address
 
1224
 * on an interface.
 
1225
 */
 
1226
void bootaddr( iface )
 
1227
    struct interface    *iface;
 
1228
{
 
1229
    if ( iface == 0 ) {
 
1230
        return;
 
1231
    }
 
1232
 
 
1233
    /* consistency */
 
1234
    if ( iface->i_flags & IFACE_ADDR ) {
 
1235
        LOG(log_error, logtype_atalkd, "bootaddr OOPS!" );
 
1236
        atalkd_exit(1);
 
1237
    }
 
1238
 
 
1239
    if ( iface->i_flags & IFACE_PHASE1 ) {
 
1240
        setaddr( iface, IFACE_PHASE1, 0,
 
1241
                iface->i_caddr.sat_addr.s_node, 0, 0 );
 
1242
 
 
1243
        if ( iface->i_flags & IFACE_LOOPBACK ) {
 
1244
            iface->i_flags |= IFACE_CONFIG | IFACE_ADDR;
 
1245
            if ( ciface == iface ) {
 
1246
                ciface = ciface->i_next;
 
1247
                bootaddr( ciface );
 
1248
            }
 
1249
 
 
1250
        } else if (rtmp_request( iface ) < 0) {
 
1251
          LOG(log_error, logtype_atalkd, "bootaddr (rtmp_request): %s", strerror(errno));
 
1252
          atalkd_exit(1);
 
1253
        }
 
1254
 
 
1255
    } else {
 
1256
        setaddr( iface, IFACE_PHASE2, iface->i_caddr.sat_addr.s_net,
 
1257
                iface->i_caddr.sat_addr.s_node,
 
1258
                iface->i_rt->rt_firstnet, iface->i_rt->rt_lastnet );
 
1259
 
 
1260
        if ( iface->i_flags & IFACE_LOOPBACK ) {
 
1261
            iface->i_flags |= IFACE_CONFIG | IFACE_ADDR;
 
1262
            if ( ciface == iface ) {
 
1263
                ciface = ciface->i_next;
 
1264
                bootaddr( ciface );
 
1265
            }
 
1266
            
 
1267
        } else if (zip_getnetinfo( iface ) < 0) {
 
1268
          LOG(log_error, logtype_atalkd, "bootaddr (zip_getnetinfo): %s", strerror(errno));
 
1269
          atalkd_exit(1);
 
1270
        }
 
1271
    }
 
1272
    ++iface->i_time;
 
1273
    iface->i_flags |= IFACE_ADDR;
 
1274
    stabletimer = UNSTABLE;
 
1275
}
 
1276
 
 
1277
 
 
1278
/*
 
1279
 * Change setaddr()
 
1280
 * to manage the i_ports field and the fds for select().
 
1281
 */
 
1282
void setaddr(struct interface *iface,
 
1283
             u_int8_t  phase, u_int16_t net, u_int8_t node,
 
1284
             u_int16_t first, u_int16_t last)
 
1285
{
 
1286
    int                 i;
 
1287
    struct atserv       *as;
 
1288
    struct atport       *ap;
 
1289
    struct servent      *se;
 
1290
    struct sockaddr_at  sat;
 
1291
    struct netrange     nr;
 
1292
 
 
1293
    if ( iface->i_ports == NULL ) {     /* allocate port structures */
 
1294
        for ( i = 0, as = atserv; i < atservNATSERV; i++, as++ ) {
 
1295
            if (( se = getservbyname( as->as_name, "ddp" )) == NULL ) {
 
1296
                LOG(log_info, logtype_atalkd, "%s: service unknown", as->as_name );
 
1297
            } else {
 
1298
                as->as_port = ntohs( se->s_port );
 
1299
            }
 
1300
            if (( ap = (struct atport *)malloc( sizeof( struct atport ))) ==
 
1301
                    NULL ) {
 
1302
                LOG(log_error, logtype_atalkd, "malloc: %s", strerror(errno) );
 
1303
                atalkd_exit( 1 );
 
1304
            }
 
1305
            ap->ap_fd = 0;
 
1306
            ap->ap_next = iface->i_ports;
 
1307
            ap->ap_iface = iface;
 
1308
            ap->ap_port = as->as_port;
 
1309
            ap->ap_packet = as->as_packet;
 
1310
 
 
1311
            iface->i_ports = ap;
 
1312
        }
 
1313
    } else {                            /* close ports */
 
1314
        for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
 
1315
            (void)close( ap->ap_fd );
 
1316
        }
 
1317
    }
 
1318
 
 
1319
#ifdef BSD4_4
 
1320
    iface->i_addr.sat_len = sizeof( struct sockaddr_at );
 
1321
#endif /* BSD4_4 */
 
1322
    iface->i_addr.sat_family = AF_APPLETALK;
 
1323
    iface->i_addr.sat_addr.s_net = net;
 
1324
    iface->i_addr.sat_addr.s_node = node;
 
1325
 
 
1326
    nr.nr_phase = phase;
 
1327
    nr.nr_firstnet = first;
 
1328
    nr.nr_lastnet = last;
 
1329
    memcpy( iface->i_addr.sat_zero, &nr, sizeof( struct netrange ));
 
1330
 
 
1331
    if ( ifconfig( iface->i_name, SIOCSIFADDR, &iface->i_addr )) {
 
1332
      LOG(log_error, logtype_atalkd, "setifaddr: %s (%u-%u): %s. try specifying a \
 
1333
smaller net range.", iface->i_name, ntohs(first), ntohs(last), strerror(errno));
 
1334
        atalkd_exit( 1 );
 
1335
    }
 
1336
    if ( ifconfig( iface->i_name, SIOCGIFADDR, &iface->i_addr )) {
 
1337
        LOG(log_error, logtype_atalkd, "getifaddr: %s: %s", iface->i_name, strerror(errno) );
 
1338
        atalkd_exit( 1 );
 
1339
    }
 
1340
 
 
1341
    /* open ports */
 
1342
    i = 1; /* enable broadcasts */
 
1343
#ifdef __svr4__ 
 
1344
    LOG(log_info, logtype_atalkd, "setsockopt incompatible w/ Solaris STREAMS module.");
 
1345
#endif /* __svr4__ */
 
1346
    for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
 
1347
        if (( ap->ap_fd = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
 
1348
            LOG(log_error, logtype_atalkd, "socket: %s", strerror(errno) );
 
1349
            atalkd_exit( 1 );
 
1350
        }
 
1351
#ifndef __svr4__
 
1352
        setsockopt(ap->ap_fd, SOL_SOCKET, SO_BROADCAST, &i, sizeof(i));
 
1353
#endif /* ! __svr4 */
 
1354
 
 
1355
        memset( &sat, 0, sizeof( struct sockaddr_at ));
 
1356
#ifdef BSD4_4
 
1357
        sat.sat_len = sizeof( struct sockaddr_at );
 
1358
#endif /* BSD4_4 */
 
1359
        sat.sat_family = AF_APPLETALK;
 
1360
        sat.sat_addr.s_net = iface->i_addr.sat_addr.s_net;
 
1361
        sat.sat_addr.s_node = iface->i_addr.sat_addr.s_node;
 
1362
        sat.sat_port = ap->ap_port;
 
1363
 
 
1364
        if ( bind( ap->ap_fd, (struct sockaddr *)&sat,
 
1365
                sizeof( struct sockaddr_at )) < 0 ) {
 
1366
            LOG(log_error, logtype_atalkd, "bind %u.%u:%u: %s",
 
1367
                    ntohs( sat.sat_addr.s_net ),
 
1368
                    sat.sat_addr.s_node, sat.sat_port, strerror(errno) );
 
1369
#ifdef SIOCDIFADDR
 
1370
            /* remove all interfaces if we have a problem with bind */
 
1371
            for (iface = interfaces; iface; iface = iface->i_next) {
 
1372
              if (ifconfig( iface->i_name, SIOCDIFADDR, &iface->i_addr )) {
 
1373
#ifdef SIOCATALKDIFADDR
 
1374
#if (SIOCDIFADDR != SIOCATALKDIFADDR)
 
1375
                ifconfig( iface->i_name, SIOCATALKDIFADDR, &iface->i_addr );
 
1376
#endif /* SIOCDIFADDR != SIOCATALKDIFADDR */
 
1377
#endif /* SIOCATALKDIFADDR */
 
1378
              }
 
1379
            }
 
1380
#endif /* SIOCDIFADDR */
 
1381
            atalkd_exit( 1 );
 
1382
        }
 
1383
    }
 
1384
 
 
1385
    /* recalculate nfds and fds */
 
1386
    FD_ZERO( &fds );
 
1387
    for ( nfds = 0, iface = interfaces; iface; iface = iface->i_next ) {
 
1388
        for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
 
1389
            FD_SET( ap->ap_fd, &fds );
 
1390
            if ( ap->ap_fd > nfds ) {
 
1391
                nfds = ap->ap_fd;
 
1392
            }
 
1393
        }
 
1394
    }
 
1395
    nfds++;
 
1396
}
 
1397
 
 
1398
int ifconfig( iname, cmd, sa )
 
1399
    const char          *iname;
 
1400
    unsigned long       cmd;
 
1401
    struct sockaddr_at  *sa;
 
1402
{
 
1403
    struct ifreq        ifr;
 
1404
    int                 s;
 
1405
 
 
1406
    memset(&ifr, 0, sizeof(ifr));
 
1407
    strcpy( ifr.ifr_name, iname );
 
1408
    ifr.ifr_addr = *(struct sockaddr *)sa;
 
1409
 
 
1410
    if (( s = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
 
1411
        return( 1 );
 
1412
    }
 
1413
    if ( ioctl( s, cmd, &ifr ) < 0 ) {
 
1414
        close(s);
 
1415
        return( 1 );
 
1416
    }
 
1417
    close( s );
 
1418
    if ( cmd == SIOCGIFADDR ) {
 
1419
        *(struct sockaddr *)sa = ifr.ifr_addr;
 
1420
    }
 
1421
    return( 0 );
 
1422
}
 
1423
 
 
1424
void dumpconfig( iface )
 
1425
    struct interface    *iface;
 
1426
{
 
1427
    struct list         *l;
 
1428
 
 
1429
    printf( "%s", iface->i_name );
 
1430
    if ( iface->i_flags & IFACE_RSEED ) {
 
1431
        printf( " -router" );
 
1432
    } else if ( iface->i_flags & IFACE_SEED ) {
 
1433
        printf( " -seed" );
 
1434
    }
 
1435
 
 
1436
    if ( iface->i_flags & IFACE_DONTROUTE) 
 
1437
        printf( " -dontroute");
 
1438
 
 
1439
    printf( " -phase" );
 
1440
    if ( iface->i_flags & IFACE_PHASE1 ) {
 
1441
        printf( " 1" );
 
1442
    } else {
 
1443
        printf( " 2" );
 
1444
    }
 
1445
    printf( " -net %d", ntohs( iface->i_rt->rt_firstnet ));
 
1446
    if ( iface->i_rt->rt_lastnet != iface->i_rt->rt_firstnet ) {
 
1447
        printf( "-%d", ntohs( iface->i_rt->rt_lastnet ));
 
1448
    }
 
1449
    printf( " -addr %u.%u", ntohs( iface->i_addr.sat_addr.s_net ),
 
1450
            iface->i_addr.sat_addr.s_node );
 
1451
    printf( " -caddr %u.%u", ntohs( iface->i_caddr.sat_addr.s_net ),
 
1452
            iface->i_caddr.sat_addr.s_node );
 
1453
    for ( l = iface->i_rt->rt_zt; l; l = l->l_next ) {
 
1454
        printf( " -zone %.*s", ((struct ziptab *)l->l_data)->zt_len,
 
1455
                ((struct ziptab *)l->l_data)->zt_name );
 
1456
    }
 
1457
    printf( "\n" );
 
1458
}
 
1459
 
 
1460
#ifdef DEBUG
 
1461
void dumproutes()
 
1462
{
 
1463
    struct interface    *iface;
 
1464
    struct rtmptab      *rtmp;
 
1465
    struct list         *l;
 
1466
    struct ziptab       *zt;
 
1467
 
 
1468
    for ( iface = interfaces; iface; iface = iface->i_next ) {
 
1469
        for ( rtmp = iface->i_rt; rtmp; rtmp = rtmp->rt_inext ) {
 
1470
            if ( rtmp->rt_gate == 0 ) {
 
1471
                if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
 
1472
                    printf( "%u-%u", ntohs( rtmp->rt_firstnet ),
 
1473
                            ntohs( rtmp->rt_lastnet ));
 
1474
                } else {
 
1475
                    printf( "%u", ntohs( rtmp->rt_firstnet ));
 
1476
                }
 
1477
            } else {
 
1478
                if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
 
1479
                    printf( "%u.%u for %u-%u",
 
1480
                            ntohs( rtmp->rt_gate->g_sat.sat_addr.s_net ),
 
1481
                            rtmp->rt_gate->g_sat.sat_addr.s_node,
 
1482
                            ntohs( rtmp->rt_firstnet ),
 
1483
                            ntohs( rtmp->rt_lastnet ));
 
1484
                } else {
 
1485
                    printf( "%u.%u for %u",
 
1486
                            ntohs( rtmp->rt_gate->g_sat.sat_addr.s_net ),
 
1487
                            rtmp->rt_gate->g_sat.sat_addr.s_node,
 
1488
                            ntohs( rtmp->rt_firstnet ));
 
1489
                }
 
1490
            }
 
1491
 
 
1492
            if ( rtmp->rt_iprev == 0 && rtmp != iface->i_rt ) {
 
1493
                printf( " *" );
 
1494
            }
 
1495
 
 
1496
            for ( l = rtmp->rt_zt; l; l = l->l_next ) {
 
1497
                zt = (struct ziptab *)l->l_data;
 
1498
                printf( " %.*s", zt->zt_len, zt->zt_name );
 
1499
            }
 
1500
 
 
1501
            printf( "\n" );
 
1502
        }
 
1503
    }
 
1504
 
 
1505
    printf( "\n" );
 
1506
    fflush( stdout );
 
1507
}
 
1508
 
 
1509
void dumpzones()
 
1510
{
 
1511
    struct interface    *iface;
 
1512
    struct rtmptab      *rtmp;
 
1513
    struct list         *l;
 
1514
    struct ziptab       *zt;
 
1515
 
 
1516
    for ( zt = ziptab; zt; zt = zt->zt_next ) {
 
1517
        printf( "%.*s", zt->zt_len, zt->zt_name );
 
1518
        for ( l = zt->zt_rt; l; l = l->l_next ) {
 
1519
            rtmp = (struct rtmptab *)l->l_data;
 
1520
            if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
 
1521
                printf( " %u-%u", ntohs( rtmp->rt_firstnet ),
 
1522
                        ntohs( rtmp->rt_lastnet ));
 
1523
            } else {
 
1524
                printf( " %u", ntohs( rtmp->rt_firstnet ));
 
1525
            }
 
1526
            if ( rtmp->rt_iprev == 0 && rtmp->rt_gate != 0 ) {
 
1527
                printf( "*" );
 
1528
            }
 
1529
        }
 
1530
        printf( "\n" );
 
1531
    }
 
1532
 
 
1533
    printf( "\n" );
 
1534
    fflush( stdout );
 
1535
}
 
1536
#endif /* DEBUG */