2
* $Id: main.c,v 1.17 2002/10/05 13:20:13 didg Exp $
4
* Copyright (c) 1990,1993 Regents of The University of Michigan.
5
* All Rights Reserved. See COPYRIGHT.
10
#endif /* HAVE_CONFIG_H */
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__ */
18
#endif /* sun __svr4__ */
20
#include <sys/resource.h>
21
#include <sys/ioctl.h>
24
#include <sys/types.h>
25
#ifdef HAVE_SYS_WAIT_H
27
#endif /* HAVE_SYS_WAIT_H */
29
#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
30
#endif /* ! WEXITSTATUS */
32
#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
33
#endif /* ! WIFEXITED */
35
#define WIFSTOPPED(status) (((status) & 0xff) == 0x7f)
41
#include <net/route.h>
44
#include <net/route.h>
46
#include <netinet/in.h>
49
#include <atalk/logger.h>
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>
68
#include <sys/sockio.h>
72
#include "interface.h"
80
/* Forward Declarations */
81
int ifconfig(const char *iname, unsigned long cmd, struct sockaddr_at *sa);
83
/* FIXME/SOCKLEN_T: socklen_t is a unix98 feature */
85
#define SOCKLEN_T unsigned int
86
#endif /* SOCKLEN_T */
89
#define WEXITSTATUS(x) ((x).w_retcode)
90
#endif /* WEXITSTATUS */
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
96
#if !defined(SIOCDIFADDR) && defined(SIOCATALKDIFADDR)
97
#define SIOCDIFADDR SIOCATALKDIFADDR
100
#define elements(a) (sizeof(a)/sizeof((a)[0]))
104
extern int rtmp_packet();
105
extern int nbp_packet();
106
extern int aep_packet();
107
extern int zip_packet();
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 */
117
int atservNATSERV = elements( atserv );
119
struct interface *interfaces = NULL, *ciface = NULL;
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;
129
char Packet[ PKTSZ ];
130
char *version = VERSION;
131
static char *pidfile = _PATH_ATALKDLOCK;
136
int readconf( char * );
137
int getifconf( void );
138
int writeconf( char * );
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)
145
struct interface *iface;
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))
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));
160
#endif /* SOPCDOFADDR */
162
server_unlock(pidfile);
167
static void as_timer(int sig)
169
struct sockaddr_at sat;
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;
178
char *data, *end, packet[ ATP_BUFSIZ ];
182
memset(&sat, 0, sizeof( struct sockaddr_at ));
183
for ( iface = interfaces; iface; iface = iface->i_next ) {
184
if ( iface->i_flags & IFACE_LOOPBACK ) {
187
for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
188
if ( ap->ap_packet == zip_packet ) {
191
if ( ap->ap_packet == rtmp_packet ) {
196
if (( iface->i_flags & ( IFACE_ADDR|IFACE_CONFIG|IFACE_NOROUTER )) ==
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));
206
if (zip_getnetinfo( iface ) < 0) {
207
LOG(log_error, logtype_atalkd, "zip_getnetinfo: %s", strerror(errno));
214
iface->i_flags |= IFACE_NOROUTER;
215
if ((iface->i_flags & IFACE_ISROUTER)) {
216
if (( iface->i_flags & IFACE_SEED ) == 0 ) {
218
* No seed info, and we've got multiple interfaces.
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",
225
LOG(log_info, logtype_atalkd, "as_timer waiting for router" );
230
* Complete configuration for iface, and boot next
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,
237
LOG(log_error, logtype_atalkd, "addzone: %s", strerror(errno));
241
if ( iface->i_rt->rt_zt ) {
242
iface->i_rt->rt_flags &= ~RTMPTAB_ZIPQUERY;
243
iface->i_rt->rt_flags |= RTMPTAB_HASZONES;
245
if ( iface->i_flags & IFACE_PHASE1 ) {
246
LOG(log_info, logtype_atalkd,
247
"as_timer configured %s phase 1 from seed",
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 );
255
LOG(log_info, logtype_atalkd,
256
"as_timer configured %s phase 2 from seed",
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,
268
if ( iface == ciface ) {
269
ciface = ciface->i_next;
275
* Configure for no router operation. Wait for a route
276
* to become available in rtmp_packet().
278
LOG(log_info, logtype_atalkd, "config for no router" );
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 ));
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,
297
if ( iface == ciface ) {
298
ciface = ciface->i_next;
305
for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
307
free( (caddr_t)fgate );
312
data = packet + 1 + sizeof( struct ziphdr );
313
end = packet + sizeof( packet );
316
sat.sat_port = zap->ap_port;
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.
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 );
329
frtmp = rtmp->rt_next;
330
if ( rtmp->rt_hops == RTMPHOPS_POISON ||
331
rtmp->rt_iprev == 0 ) {
334
rtmp->rt_hops = RTMPHOPS_POISON;
335
if ((cc = rtmp_replace( rtmp )) < 0) {
336
LOG(log_error, logtype_atalkd, "rtmp_replace: %s", strerror(errno));
340
gate->g_state = rtmp->rt_state = RTMPTAB_GOOD;
345
if ( gate->g_rt == 0 ) {
346
if ( gate->g_prev == 0 ) {
347
gate->g_iface->i_gate = gate->g_next;
349
gate->g_prev->g_next = gate->g_next;
351
if ( gate->g_next != 0 ) {
352
gate->g_next->g_prev = gate->g_prev;
354
fgate = gate; /* can't free here, just mark it */
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
362
* XXX: actually, we always reconfigure an interface
363
* if we're not a seed router.
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;
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;
377
LOG(log_info, logtype_atalkd, "as_timer last gateway down" );
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 ));
394
* If we don't have a zone for our interface yet, ask for
395
* it from any router (all routers) on the interface.
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 );
407
* Delete old routing tuples.
409
if ( rtmp->rt_state != RTMPTAB_PERM ) {
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.
422
if ( rtmp->rt_state >= RTMPTAB_BAD ) {
423
frtmp = rtmp->rt_next;
424
if ( rtmp->rt_iprev == 0 ) { /* not in use */
426
} else { /* in use */
427
if ( rtmp->rt_hops == RTMPHOPS_POISON ) {
430
rtmp->rt_hops = RTMPHOPS_POISON;
431
if ((cc = rtmp_replace( rtmp )) < 0) {
432
LOG(log_error, logtype_atalkd, "rtmp_replace: %s", strerror(errno));
436
rtmp->rt_state = RTMPTAB_GOOD;
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;
454
*data++ = DDPTYPE_ZIP;
455
memcpy( data, &zh, sizeof( struct ziphdr ));
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) );
465
data = packet + 1 + sizeof( struct ziphdr );
466
end = packet + sizeof( packet );
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.
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 ));
482
if ( rtmp->rt_nzq > 3 ) {
484
rtmp = rtmp->rt_next;
490
rtmp->rt_flags |= RTMPTAB_ZIPQUERY;
491
memcpy( data, &rtmp->rt_firstnet, sizeof( u_short ));
492
data += sizeof( u_short );
495
rtmp = rtmp->rt_next;
498
/* send what we've got */
500
zh.zh_op = ZIPOP_QUERY;
504
*data++ = DDPTYPE_ZIP;
505
memcpy( data, &zh, sizeof( struct ziphdr ));
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) );
514
free( (caddr_t)fgate );
519
* Send RTMP broadcasts if we have multiple interfaces or our
520
* interface is configured as a router.
522
if ((iface->i_flags & IFACE_ISROUTER)) {
524
sat.sat_len = sizeof( struct sockaddr_at );
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;
532
end = data + sizeof( packet );
533
*data++ = DDPTYPE_RTMPRD;
534
rh.rh_net = iface->i_addr.sat_addr.s_net;
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 );
542
if ( iface->i_flags & IFACE_PHASE1 ) {
545
memcpy( data, &rt, SZ_RTMPTUPLE );
546
data += SZ_RTMPTUPLE;
548
rt.rt_net = iface->i_rt->rt_firstnet;
550
memcpy( data, &rt, SZ_RTMPTUPLE );
551
data += SZ_RTMPTUPLE;
553
rt.rt_net = iface->i_rt->rt_lastnet;
555
memcpy( data, &rt, SZ_RTMPTUPLE );
556
data += SZ_RTMPTUPLE;
559
for ( iface2 = interfaces; iface2; iface2 = iface2->i_next ) {
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)) {
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.
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 ) {
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 ),
591
ntohs( iface->i_rt->rt_firstnet ),
595
if ( iface->i_flags & IFACE_PHASE2 ) {
596
data = packet + 1 + sizeof( struct rtmp_head ) +
599
data = packet + 1 + sizeof( struct rtmp_head ) +
605
rt.rt_net = rtmp->rt_firstnet;
606
rt.rt_dist = rtmp->rt_hops;
607
if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
610
memcpy( data, &rt, SZ_RTMPTUPLE );
611
data += SZ_RTMPTUPLE;
613
if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
614
rt.rt_net = rtmp->rt_lastnet;
616
memcpy( data, &rt, SZ_RTMPTUPLE );
617
data += SZ_RTMPTUPLE;
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 ),
631
ntohs( iface->i_rt->rt_firstnet ),
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.
646
if ( stabletimer <= STABLE && !newrtmpdata && !sentzipq ) {
647
/* write out config file */
649
writeconf( configfile );
651
if ( stabletimer-- <= STABLEANYWAY ) {
657
if ( stable && !noparent ) {
659
LOG(log_info, logtype_atalkd, "ready %d/%d/%d", stabletimer, newrtmpdata,
663
* Seems like we could get here more than once...
665
if ( kill( getpid(), SIGSTOP ) < 0 ) {
666
LOG(log_error, logtype_atalkd, "as_timer: kill-self failed!" );
680
* Consistency check...
684
struct rtmptab *rtmp;
685
struct list *lr, *lz;
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 ));
697
for ( lz = rtmp->rt_zt; lz; lz = lz->l_next ) {
698
if ( zt == (struct ziptab *)lz->l_data ) {
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 );
714
#if !defined( ibm032 ) && !defined( _IBMR2 )
716
#endif /* ! ibm032 && ! _IBMR2 */
719
struct interface *iface;
726
if (( rtmpdebug = fopen( _PATH_ATALKDEBUG, "w" )) == NULL ) {
727
LOG(log_error, logtype_atalkd, "rtmp: %s", strerror(errno) );
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 );
737
if ( iface->i_flags & IFACE_PHASE2 ) {
738
putc( '2', rtmpdebug );
740
if ( iface->i_flags & IFACE_RSEED ) {
741
putc( 'R', rtmpdebug );
743
if ( iface->i_flags & IFACE_SEED ) {
744
putc( 'S', rtmpdebug );
746
if ( iface->i_flags & IFACE_DONTROUTE ) {
747
putc( 'D', rtmpdebug );
749
if ( iface->i_flags & IFACE_ADDR ) {
750
putc( 'A', rtmpdebug );
752
if ( iface->i_flags & IFACE_CONFIG ) {
753
putc( 'C', rtmpdebug );
755
if ( iface->i_flags & IFACE_NOROUTER ) {
756
putc( 'N', rtmpdebug );
758
if ( iface->i_flags & IFACE_LOOP ) {
759
putc( 'L', rtmpdebug );
761
putc( '\n', rtmpdebug );
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 );
770
if ( iface->i_rt->rt_flags & RTMPTAB_HASZONES ) {
771
putc( 'z', rtmpdebug );
773
if ( iface->i_rt->rt_flags & RTMPTAB_EXTENDED ) {
774
putc( 'x', rtmpdebug );
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 );
781
fprintf( rtmpdebug, "\n" );
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 );
794
if ( rt->rt_flags & RTMPTAB_HASZONES ) {
795
putc( 'z', rtmpdebug );
797
if ( rt->rt_flags & RTMPTAB_EXTENDED ) {
798
putc( 'x', rtmpdebug );
800
if ( rt->rt_iprev ) {
801
putc( 'i', rtmpdebug );
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 );
807
fprintf( rtmpdebug, "\n" );
816
* Called when SIGTERM is recieved. Remove all routes and then exit.
818
#if !defined( ibm032 ) && !defined( _IBMR2 )
820
#endif /* ! ibm032 && ! _IBMR2 */
823
struct interface *iface;
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 ),
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,
850
LOG(log_info, logtype_atalkd, "done" );
861
struct sockaddr_at sat;
864
struct interface *iface;
873
while (( c = getopt( ac, av, "12qsdtf:P:v" )) != EOF ) {
876
defphase = IFACE_PHASE1;
880
defphase = IFACE_PHASE2;
891
case 'q' : /* don't seed */
895
case 's' : /* seed */
899
case 't' : /* transition */
903
case 'P' : /* pid file */
907
case 'v' : /* version */
908
printf( "atalkd (version %s)\n", version );
913
fprintf( stderr, "Unknown option -- '%c'\n", c );
917
if ( optind != ac ) {
918
fprintf( stderr, "Too many arguments.\n" );
922
if (( prog = strrchr( av[ 0 ], '/' )) == NULL ) {
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
934
if (( interfaces = newiface( LOOPIFACE )) == NULL ) {
935
perror( "newiface" );
938
interfaces->i_flags |= IFACE_PHASE2 | IFACE_LOOPBACK;
941
* Check our initial configuration before we fork. This way we can
942
* complain about syntax errors on stdout.
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.
948
if ( readconf( configfile ) < 0 && getifconf() < 0 ) {
949
fprintf( stderr, "%s: can't get interfaces, exiting.\n", prog );
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)
962
i = ninterfaces - i; /* number of routable interfaces */
965
* At this point, we have (at least partially) initialized data
966
* structures. Fill in what we can and verify that nothing is obviously
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;
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;
983
/* Set default addresses */
984
if ( iface->i_rt == NULL ) {
985
if (( iface->i_rt = newrt(iface)) == NULL ) {
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;
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;
999
iface->i_rt->rt_firstnet = htons( STARTUP_FIRSTNET );
1000
iface->i_rt->rt_lastnet = htons( STARTUP_LASTNET );
1005
if (( iface->i_flags & IFACE_PHASE1 ) == 0 ) {
1006
iface->i_rt->rt_flags |= RTMPTAB_EXTENDED;
1009
if ( iface->i_caddr.sat_addr.s_net == ATADDR_ANYNET ) {
1010
iface->i_caddr.sat_addr.s_net = iface->i_rt->rt_firstnet;
1014
dumpconfig( iface ); /* probably needs args */
1019
* A little consistency check...
1021
if ( ninterfaces < IFBASE ) {
1022
fprintf( stderr, "%s: zero interfaces, exiting.\n", prog );
1026
/* do this here so that we can use ifconfig */
1028
if ( plumb() < 0 ) {
1029
fprintf(stderr, "can't establish STREAMS plumbing, exiting.\n" );
1032
#endif /* __svr4__ */
1034
/* delete pre-existing interface addresses. */
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 */
1045
#endif /* SIOCDIFADDR */
1048
* Disassociate. The child will send itself a signal when it is
1049
* stable. This indicates that other processes may begin using
1052
switch (i = server_lock("atalkd", pidfile, debug)) {
1057
default: /* parent */
1059
* Wait for the child to send itself a SIGSTOP, after which
1060
* we send it a SIGCONT and exit ourself.
1062
if ( wait3( &status, WUNTRACED, (struct rusage *)0 ) != i) {
1063
perror( "wait3" ); /* Child died? */
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 ));
1072
fprintf( stderr, " Child died.\n" );
1076
if ( kill(i, SIGCONT ) < 0 ) {
1084
openlog( prog, LOG_PID );
1086
set_processname(prog);
1087
syslog_setup(log_debug, logtype_default, logoption_pid, logfacility_daemon );
1090
LOG(log_info, logtype_atalkd, "restart (%s)", version );
1093
* Socket for use in routing ioctl()s. Can't add routes to our
1094
* interfaces until we have our routing socket.
1097
if (( rtfd = socket( PF_ROUTE, SOCK_RAW, AF_APPLETALK )) < 0 ) {
1098
LOG(log_error, logtype_atalkd, "route socket: %s", strerror(errno) );
1101
if ( shutdown( rtfd, 0 ) < 0 ) {
1102
LOG(log_error, logtype_atalkd, "route shutdown: %s", strerror(errno) );
1106
if (( rtfd = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1107
LOG(log_error, logtype_atalkd, "route socket: %s", strerror(errno) );
1112
ciface = interfaces;
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) );
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) );
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) );
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) );
1160
if ( select( nfds, &readfds, NULL, NULL, NULL) < 0 ) {
1161
if ( errno == EINTR ) {
1165
LOG(log_error, logtype_atalkd, "select: %s", strerror(errno) );
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) );
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 );
1190
if ( sighold( SIGALRM ) || sighold( SIGUSR1 )) {
1191
LOG(log_error, logtype_atalkd, "sighold: %s", strerror(errno) );
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));
1207
if ( sigrelse( SIGUSR1 ) || sigrelse( SIGALRM )) {
1208
LOG(log_error, logtype_atalkd, "sigrelse: %s", strerror(errno) );
1211
#else /* __svr4__ */
1213
#endif /* __svr4__ */
1222
* This code is called (from main(), as_timer(), zip_packet(),
1223
* and rtmp_packet()) to set the initial "bootstrapping" address
1226
void bootaddr( iface )
1227
struct interface *iface;
1234
if ( iface->i_flags & IFACE_ADDR ) {
1235
LOG(log_error, logtype_atalkd, "bootaddr OOPS!" );
1239
if ( iface->i_flags & IFACE_PHASE1 ) {
1240
setaddr( iface, IFACE_PHASE1, 0,
1241
iface->i_caddr.sat_addr.s_node, 0, 0 );
1243
if ( iface->i_flags & IFACE_LOOPBACK ) {
1244
iface->i_flags |= IFACE_CONFIG | IFACE_ADDR;
1245
if ( ciface == iface ) {
1246
ciface = ciface->i_next;
1250
} else if (rtmp_request( iface ) < 0) {
1251
LOG(log_error, logtype_atalkd, "bootaddr (rtmp_request): %s", strerror(errno));
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 );
1260
if ( iface->i_flags & IFACE_LOOPBACK ) {
1261
iface->i_flags |= IFACE_CONFIG | IFACE_ADDR;
1262
if ( ciface == iface ) {
1263
ciface = ciface->i_next;
1267
} else if (zip_getnetinfo( iface ) < 0) {
1268
LOG(log_error, logtype_atalkd, "bootaddr (zip_getnetinfo): %s", strerror(errno));
1273
iface->i_flags |= IFACE_ADDR;
1274
stabletimer = UNSTABLE;
1280
* to manage the i_ports field and the fds for select().
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)
1290
struct sockaddr_at sat;
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 );
1298
as->as_port = ntohs( se->s_port );
1300
if (( ap = (struct atport *)malloc( sizeof( struct atport ))) ==
1302
LOG(log_error, logtype_atalkd, "malloc: %s", strerror(errno) );
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;
1311
iface->i_ports = ap;
1313
} else { /* close ports */
1314
for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1315
(void)close( ap->ap_fd );
1320
iface->i_addr.sat_len = sizeof( struct sockaddr_at );
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;
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 ));
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));
1336
if ( ifconfig( iface->i_name, SIOCGIFADDR, &iface->i_addr )) {
1337
LOG(log_error, logtype_atalkd, "getifaddr: %s: %s", iface->i_name, strerror(errno) );
1342
i = 1; /* enable broadcasts */
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) );
1352
setsockopt(ap->ap_fd, SOL_SOCKET, SO_BROADCAST, &i, sizeof(i));
1353
#endif /* ! __svr4 */
1355
memset( &sat, 0, sizeof( struct sockaddr_at ));
1357
sat.sat_len = sizeof( struct sockaddr_at );
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;
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) );
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 */
1380
#endif /* SIOCDIFADDR */
1385
/* recalculate nfds and 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 ) {
1398
int ifconfig( iname, cmd, sa )
1401
struct sockaddr_at *sa;
1406
memset(&ifr, 0, sizeof(ifr));
1407
strcpy( ifr.ifr_name, iname );
1408
ifr.ifr_addr = *(struct sockaddr *)sa;
1410
if (( s = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1413
if ( ioctl( s, cmd, &ifr ) < 0 ) {
1418
if ( cmd == SIOCGIFADDR ) {
1419
*(struct sockaddr *)sa = ifr.ifr_addr;
1424
void dumpconfig( iface )
1425
struct interface *iface;
1429
printf( "%s", iface->i_name );
1430
if ( iface->i_flags & IFACE_RSEED ) {
1431
printf( " -router" );
1432
} else if ( iface->i_flags & IFACE_SEED ) {
1436
if ( iface->i_flags & IFACE_DONTROUTE)
1437
printf( " -dontroute");
1439
printf( " -phase" );
1440
if ( iface->i_flags & IFACE_PHASE1 ) {
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 ));
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 );
1463
struct interface *iface;
1464
struct rtmptab *rtmp;
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 ));
1475
printf( "%u", ntohs( rtmp->rt_firstnet ));
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 ));
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 ));
1492
if ( rtmp->rt_iprev == 0 && rtmp != iface->i_rt ) {
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 );
1511
struct interface *iface;
1512
struct rtmptab *rtmp;
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 ));
1524
printf( " %u", ntohs( rtmp->rt_firstnet ));
1526
if ( rtmp->rt_iprev == 0 && rtmp->rt_gate != 0 ) {