2 * $Id: main.c,v 1.7 2001-08-15 01:39:39 srittau 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/types.h>
13 #include <sys/param.h>
14 #include <sys/socket.h>
15 #if defined( sun ) && defined( __svr4__ )
16 #include </usr/ucbinclude/sys/file.h>
17 #else /* sun __svr4__ */
19 #endif /* sun __svr4__ */
21 #include <sys/resource.h>
22 #include <sys/ioctl.h>
27 #include <net/route.h>
30 #include <net/route.h>
41 #include <netatalk/endian.h>
42 #include <netatalk/at.h>
43 #include <atalk/compat.h>
44 #include <atalk/zip.h>
45 #include <atalk/rtmp.h>
46 #include <atalk/ddp.h>
47 #include <atalk/atp.h>
48 #include <atalk/paths.h>
49 #include <atalk/util.h>
52 #include <sys/sockio.h>
56 #include "interface.h"
64 /* Forward Declarations */
65 int ifconfig(const char *iname, unsigned long cmd, struct sockaddr_at *sa);
67 /* FIXME/SOCKLEN_T: socklen_t is a unix98 feature */
69 #define SOCKLEN_T unsigned int
70 #endif /* SOCKLEN_T */
73 #define WEXITSTATUS(x) ((x).w_retcode)
74 #endif /* WEXITSTATUS */
76 /* linux has a special ioctl for appletalk device destruction. as of
77 * 2.1.57, SIOCDIFADDR works w/ linux. okay, we need to deal with the
78 * fact that SIOCDIFADDR may be defined on linux despite the fact that
80 #if !defined(SIOCDIFADDR) && defined(SIOCATALKDIFADDR)
81 #define SIOCDIFADDR SIOCATALKDIFADDR
84 #define elements(a) (sizeof(a)/sizeof((a)[0]))
88 extern int rtmp_packet();
89 extern int nbp_packet();
90 extern int aep_packet();
91 extern int zip_packet();
95 struct atserv atserv[] = {
96 { "rtmp", 1, rtmp_packet }, /* 0 */
97 { "nbp", 2, nbp_packet }, /* 1 */
98 { "echo", 4, aep_packet }, /* 2 */
99 { "zip", 6, zip_packet }, /* 3 */
101 int atservNATSERV = elements( atserv );
103 struct interface *interfaces = NULL, *ciface = NULL;
105 int debug = 0, quiet = 0, chatty = 0;
106 char *configfile = NULL;
107 int ziptimeout = 0, transition = 0;
108 int stabletimer, stable = 0, newrtmpdata = 0, noparent = 0;
109 static int ninterfaces;
110 int defphase = IFACE_PHASE2;
113 char Packet[ PKTSZ ];
114 char *version = VERSION;
115 static char *pidfile = _PATH_ATALKDLOCK;
120 int readconf( char * );
121 int getifconf( void );
122 int writeconf( char * );
124 /* this is the messiest of the bunch as atalkd can exit pretty much
125 * everywhere. we delete interfaces here instead of in as_down. */
126 static void atalkd_exit(const int i)
129 struct interface *iface;
131 for (iface = interfaces; iface; iface = iface->i_next) {
132 if (ifconfig( iface->i_name, SIOCDIFADDR, &iface->i_addr)) {
133 #ifdef SIOCATALKDIFADDR
134 #if (SIOCDIFADDR != SIOCATALKDIFADDR)
135 if (!ifconfig(iface->i_name, SIOCATALKDIFADDR, &iface->i_addr))
137 #endif /* SIOCDIFADDR != SIOCATALKDIFADDR */
138 #endif /* SIOCATALKIFADDR */
139 syslog( LOG_ERR, "difaddr(%u.%u): %m",
140 ntohs(iface->i_addr.sat_addr.s_net),
141 iface->i_addr.sat_addr.s_node);
144 #endif /* SOPCDOFADDR */
146 server_unlock(pidfile);
151 #if !defined( ibm032 ) && !defined( _IBMR2 )
153 #endif /* ibm032 _IBMR2 */
156 struct sockaddr_at sat;
159 struct rtmp_tuple rt;
160 struct atport *ap, *zap, *rap;
161 struct interface *iface, *iface2;
162 struct gate *gate, *fgate = NULL;
163 struct rtmptab *rtmp, *frtmp;
165 char *data, *end, packet[ ATP_BUFSIZ ];
169 memset(&sat, 0, sizeof( struct sockaddr_at ));
170 for ( iface = interfaces; iface; iface = iface->i_next ) {
171 if ( iface->i_flags & IFACE_LOOPBACK ) {
174 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
175 if ( ap->ap_packet == zip_packet ) {
178 if ( ap->ap_packet == rtmp_packet ) {
183 if (( iface->i_flags & ( IFACE_ADDR|IFACE_CONFIG|IFACE_NOROUTER )) ==
185 if ( iface->i_time < 3 ) {
186 if ( iface->i_flags & IFACE_PHASE1 ) {
187 if (rtmp_request( iface ) < 0) {
188 syslog(LOG_ERR, "rtmp_request: %m");
193 if (zip_getnetinfo( iface ) < 0) {
194 syslog(LOG_ERR, "zip_getnetinfo: %m");
201 iface->i_flags |= IFACE_NOROUTER;
202 if ((iface->i_flags & IFACE_ISROUTER)) {
203 if (( iface->i_flags & IFACE_SEED ) == 0 ) {
205 * No seed info, and we've got multiple interfaces.
209 "as_timer multiple interfaces, no seed" );
210 syslog( LOG_INFO, "as_timer can't configure %s",
212 syslog( LOG_INFO, "as_timer waiting for router" );
217 * Complete configuration for iface, and boot next
220 iface->i_flags |= IFACE_CONFIG;
221 for ( zt = iface->i_czt; zt; zt = zt->zt_next ) {
222 if (addzone( iface->i_rt, zt->zt_len,
224 syslog(LOG_ERR, "addzone: %m");
228 if ( iface->i_rt->rt_zt ) {
229 iface->i_rt->rt_flags &= ~RTMPTAB_ZIPQUERY;
230 iface->i_rt->rt_flags |= RTMPTAB_HASZONES;
232 if ( iface->i_flags & IFACE_PHASE1 ) {
234 "as_timer configured %s phase 1 from seed",
236 setaddr( iface, IFACE_PHASE1,
237 iface->i_caddr.sat_addr.s_net,
238 iface->i_addr.sat_addr.s_node,
239 iface->i_caddr.sat_addr.s_net,
240 iface->i_caddr.sat_addr.s_net );
243 "as_timer configured %s phase 2 from seed",
247 if ( looproute( iface, RTMP_ADD )) { /* -1 or 1 */
249 "as_timer: can't route %u.%u to loop: %m",
250 ntohs( iface->i_addr.sat_addr.s_net ),
251 iface->i_addr.sat_addr.s_node );
254 if ( iface == ciface ) {
255 ciface = ciface->i_next;
261 * Configure for no router operation. Wait for a route
262 * to become available in rtmp_packet().
264 syslog( LOG_INFO, "config for no router" );
266 if ( iface->i_flags & IFACE_PHASE2 ) {
267 iface->i_rt->rt_firstnet = 0;
268 iface->i_rt->rt_lastnet = htons( STARTUP_LASTNET );
269 setaddr( iface, IFACE_PHASE2,
270 iface->i_addr.sat_addr.s_net,
271 iface->i_addr.sat_addr.s_node,
272 0, htons( STARTUP_LASTNET ));
274 if ( looproute( iface, RTMP_ADD ) ) { /* -1 or 1 */
276 "as_timer: can't route %u.%u to loopback: %m",
277 ntohs( iface->i_addr.sat_addr.s_net ),
278 iface->i_addr.sat_addr.s_node );
282 if ( iface == ciface ) {
283 ciface = ciface->i_next;
290 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
292 free( (caddr_t)fgate );
297 data = packet + 1 + sizeof( struct ziphdr );
298 end = packet + sizeof( packet );
301 sat.sat_port = zap->ap_port;
304 * Perform timeouts on routers. If we've only got one
305 * interface, we'll use these timeouts to decide that
306 * our zone has gone away.
308 if ( ++gate->g_state >= RTMPTAB_BAD ) {
309 syslog( LOG_INFO, "as_timer gateway %u.%u down",
310 ntohs( gate->g_sat.sat_addr.s_net ),
311 gate->g_sat.sat_addr.s_node );
314 frtmp = rtmp->rt_next;
315 if ( rtmp->rt_hops == RTMPHOPS_POISON ||
316 rtmp->rt_iprev == 0 ) {
319 rtmp->rt_hops = RTMPHOPS_POISON;
320 if ((cc = rtmp_replace( rtmp )) < 0) {
321 syslog(LOG_ERR, "rtmp_replace: %m");
325 gate->g_state = rtmp->rt_state = RTMPTAB_GOOD;
330 if ( gate->g_rt == 0 ) {
331 if ( gate->g_prev == 0 ) {
332 gate->g_iface->i_gate = gate->g_next;
334 gate->g_prev->g_next = gate->g_next;
336 if ( gate->g_next != 0 ) {
337 gate->g_next->g_prev = gate->g_prev;
339 fgate = gate; /* can't free here, just mark it */
342 * If this is the last router on the only interface,
343 * reconfigure our netrange. By marking the interface
344 * as having no router, we will notice when a router
347 * XXX: actually, we always reconfigure an interface
348 * if we're not a seed router.
351 if ( gate->g_iface->i_gate == 0 &&
352 ((iface->i_flags & IFACE_SEED) == 0)) {
353 gate->g_iface->i_flags |= IFACE_NOROUTER;
354 gate->g_iface->i_flags &= ~IFACE_CONFIG;
356 /* get rid of any zones associated with this iface */
357 if (gate->g_iface->i_rt->rt_zt) {
358 rtmp_delzonemap(gate->g_iface->i_rt);
359 gate->g_iface->i_rt->rt_flags &= ~RTMPTAB_HASZONES;
362 syslog( LOG_INFO, "as_timer last gateway down" );
364 /* Set netrange to 0-fffe. */
365 if ( gate->g_iface->i_flags & IFACE_PHASE2 ) {
366 gate->g_iface->i_rt->rt_firstnet = 0;
367 gate->g_iface->i_rt->rt_lastnet =
368 htons( STARTUP_LASTNET );
369 setaddr( iface, IFACE_PHASE2,
370 iface->i_addr.sat_addr.s_net,
371 iface->i_addr.sat_addr.s_node,
372 0, htons( STARTUP_LASTNET ));
379 * If we don't have a zone for our interface yet, ask for
380 * it from any router (all routers) on the interface.
382 if (( iface->i_rt->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
383 iface->i_rt->rt_flags |= RTMPTAB_ZIPQUERY;
384 memcpy( data, &iface->i_rt->rt_firstnet, sizeof( u_short ));
385 data += sizeof( u_short );
392 * Delete old routing tuples.
394 if ( rtmp->rt_state != RTMPTAB_PERM ) {
399 * We've not been updated for this route in a while. If
400 * it's not in use, go ahead and remove it. If it is in
401 * use, mark the route as down (POISON), and look for a
402 * better route. If one is found, delete this route and use
403 * the new one. If it's not found, mark the route as GOOD
404 * (so we'll propogate our poison) and delete it the next
405 * time it becomes BAD.
407 if ( rtmp->rt_state >= RTMPTAB_BAD ) {
408 frtmp = rtmp->rt_next;
409 if ( rtmp->rt_iprev == 0 ) { /* not in use */
411 } else { /* in use */
412 if ( rtmp->rt_hops == RTMPHOPS_POISON ) {
415 rtmp->rt_hops = RTMPHOPS_POISON;
416 if ((cc = rtmp_replace( rtmp )) < 0) {
417 syslog(LOG_ERR, "rtmp_replace: %m");
421 rtmp->rt_state = RTMPTAB_GOOD;
431 if ( rtmp->rt_iprev &&
432 ( rtmp->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
433 if ( data + sizeof( u_short ) > end || n == 255 ) {
434 /* send what we've got */
435 zh.zh_op = ZIPOP_QUERY;
439 *data++ = DDPTYPE_ZIP;
440 memcpy( data, &zh, sizeof( struct ziphdr ));
442 if ( sendto( zap->ap_fd, packet, cc, 0,
443 (struct sockaddr *)&sat,
444 sizeof( struct sockaddr_at )) < 0 ) {
445 syslog( LOG_ERR, "as_timer sendto: %m" );
450 data = packet + 1 + sizeof( struct ziphdr );
451 end = packet + sizeof( packet );
455 * rt_nzq is number of ZIP Queries we've issued for a
456 * given netrange. If we've got ziptimeout on, we
457 * will only ask 3 times for any given netrange.
458 * Interestingly enough, since rt_nzq is a u_char,
459 * it will overflow after a while. This means we will
460 * periodically ask for nets that we've decided not to
461 * ask about, and warn that we can't get it's zone.
463 if ( rtmp->rt_nzq++ == 3 ) {
464 syslog( LOG_INFO, "as_timer can't get zone for %u",
465 ntohs( rtmp->rt_firstnet ));
467 if ( rtmp->rt_nzq > 3 ) {
469 rtmp = rtmp->rt_next;
475 rtmp->rt_flags |= RTMPTAB_ZIPQUERY;
476 memcpy( data, &rtmp->rt_firstnet, sizeof( u_short ));
477 data += sizeof( u_short );
480 rtmp = rtmp->rt_next;
483 /* send what we've got */
485 zh.zh_op = ZIPOP_QUERY;
489 *data++ = DDPTYPE_ZIP;
490 memcpy( data, &zh, sizeof( struct ziphdr ));
492 if ( sendto( zap->ap_fd, packet, cc, 0, (struct sockaddr *)&sat,
493 sizeof( struct sockaddr_at )) < 0 ) {
494 syslog( LOG_ERR, "as_timer sendto: %m" );
499 free( (caddr_t)fgate );
504 * Send RTMP broadcasts if we have multiple interfaces or our
505 * interface is configured as a router.
507 if ((iface->i_flags & IFACE_ISROUTER)) {
509 sat.sat_len = sizeof( struct sockaddr_at );
511 sat.sat_family = AF_APPLETALK;
512 sat.sat_addr.s_net = ATADDR_ANYNET;
513 sat.sat_addr.s_node = ATADDR_BCAST;
514 sat.sat_port = rap->ap_port;
517 end = data + sizeof( packet );
518 *data++ = DDPTYPE_RTMPRD;
519 rh.rh_net = iface->i_addr.sat_addr.s_net;
521 rh.rh_node = iface->i_addr.sat_addr.s_node;
522 memcpy( data, &rh, sizeof( struct rtmp_head ));
523 data += sizeof( struct rtmp_head );
527 if ( iface->i_flags & IFACE_PHASE1 ) {
530 memcpy( data, &rt, SZ_RTMPTUPLE );
531 data += SZ_RTMPTUPLE;
533 rt.rt_net = iface->i_rt->rt_firstnet;
535 memcpy( data, &rt, SZ_RTMPTUPLE );
536 data += SZ_RTMPTUPLE;
538 rt.rt_net = iface->i_rt->rt_lastnet;
540 memcpy( data, &rt, SZ_RTMPTUPLE );
541 data += SZ_RTMPTUPLE;
544 for ( iface2 = interfaces; iface2; iface2 = iface2->i_next ) {
546 /* XXX: there used to be a bit checking against iface ==
547 iface2. also, we don't want to send an rtmp broadcast
548 to an interface that doesn't want it. */
549 if ((( iface2->i_flags & IFACE_CONFIG ) == 0) ||
550 ((iface2->i_flags & IFACE_ISROUTER) == 0)) {
554 * Fill in tuples. Always send the same thing, regardless
555 * of the phase of the destination. Routers who don't
556 * understand extended rtmp packets will toss extended
557 * tuples because their distance will have the high bit set.
559 for ( rtmp = iface2->i_rt; rtmp; rtmp = rtmp->rt_inext ) {
560 /* don't broadcast routes we have no zone for */
561 if ( rtmp->rt_zt == 0 ||
562 ( rtmp->rt_flags & RTMPTAB_ZIPQUERY ) ||
563 ( rtmp->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
567 if ((( rtmp->rt_flags & RTMPTAB_EXTENDED ) &&
568 data + 2 * SZ_RTMPTUPLE > end ) ||
569 data + SZ_RTMPTUPLE > end ) {
570 if ( sendto( rap->ap_fd, packet, data - packet, 0,
571 (struct sockaddr *)&sat,
572 sizeof( struct sockaddr_at )) < 0 ) {
573 syslog( LOG_ERR, "as_timer sendto %u.%u (%u): %m",
574 ntohs( sat.sat_addr.s_net ),
576 ntohs( iface->i_rt->rt_firstnet ));
579 if ( iface->i_flags & IFACE_PHASE2 ) {
580 data = packet + 1 + sizeof( struct rtmp_head ) +
583 data = packet + 1 + sizeof( struct rtmp_head ) +
589 rt.rt_net = rtmp->rt_firstnet;
590 rt.rt_dist = rtmp->rt_hops;
591 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
594 memcpy( data, &rt, SZ_RTMPTUPLE );
595 data += SZ_RTMPTUPLE;
597 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
598 rt.rt_net = rtmp->rt_lastnet;
600 memcpy( data, &rt, SZ_RTMPTUPLE );
601 data += SZ_RTMPTUPLE;
609 if ( sendto( rap->ap_fd, packet, data - packet, 0,
610 (struct sockaddr *)&sat,
611 sizeof( struct sockaddr_at )) < 0 ) {
612 syslog( LOG_ERR, "as_timer sendto %u.%u (%u): %m",
613 ntohs( sat.sat_addr.s_net ),
615 ntohs( iface->i_rt->rt_firstnet ));
622 * Check if we're stable. Each time we configure an interface, we
623 * sent stabletimer to UNSTABLE. If stabletimer ever gets to
624 * STABLEANYWAY, we give up and decide to "be" stable anyway.
625 * Normally, we wait for stabletimer get <= STABLE with no new rtmp
626 * data and all zip data complete.
629 if ( stabletimer <= STABLE && !newrtmpdata && !sentzipq ) {
630 /* write out config file */
632 writeconf( configfile );
634 if ( stabletimer-- <= STABLEANYWAY ) {
640 if ( stable && !noparent ) {
642 syslog( LOG_INFO, "ready %d/%d/%d", stabletimer, newrtmpdata,
646 * Seems like we could get here more than once...
648 if ( kill( getpid(), SIGSTOP ) < 0 ) {
649 syslog( LOG_ERR, "as_timer: kill-self failed!" );
663 * Consistency check...
667 struct rtmptab *rtmp;
668 struct list *lr, *lz;
671 for ( zt = ziptab; zt; zt = zt->zt_next ) {
672 for ( lr = zt->zt_rt; lr; lr = lr->l_next ) {
673 rtmp = (struct rtmptab *)lr->l_data;
674 if ( rtmp->rt_iprev == 0 && rtmp->rt_gate != 0 ) {
675 syslog( LOG_ERR, "%.*s has %u-%u (unused)\n",
676 zt->zt_len, zt->zt_name, ntohs( rtmp->rt_firstnet ),
677 ntohs( rtmp->rt_lastnet ));
680 for ( lz = rtmp->rt_zt; lz; lz = lz->l_next ) {
681 if ( zt == (struct ziptab *)lz->l_data ) {
686 syslog( LOG_ERR, "no map from %u-%u to %.*s\n",
687 ntohs( rtmp->rt_firstnet ),
688 ntohs( rtmp->rt_lastnet ),
689 zt->zt_len, zt->zt_name );
697 #if !defined( ibm032 ) && !defined( _IBMR2 )
699 #endif /* ! ibm032 && ! _IBMR2 */
702 struct interface *iface;
709 if (( rtmpdebug = fopen( _PATH_ATALKDEBUG, "w" )) == NULL ) {
710 syslog( LOG_ERR, "rtmp: %m" );
713 for ( iface = interfaces; iface; iface = iface->i_next ) {
714 fprintf( rtmpdebug, "interface %s %u.%u ", iface->i_name,
715 ntohs( iface->i_addr.sat_addr.s_net ),
716 iface->i_addr.sat_addr.s_node );
717 if ( iface->i_flags & IFACE_PHASE1 ) {
718 putc( '1', rtmpdebug );
720 if ( iface->i_flags & IFACE_PHASE2 ) {
721 putc( '2', rtmpdebug );
723 if ( iface->i_flags & IFACE_RSEED ) {
724 putc( 'R', rtmpdebug );
726 if ( iface->i_flags & IFACE_SEED ) {
727 putc( 'S', rtmpdebug );
729 if ( iface->i_flags & IFACE_DONTROUTE ) {
730 putc( 'D', rtmpdebug );
732 if ( iface->i_flags & IFACE_ADDR ) {
733 putc( 'A', rtmpdebug );
735 if ( iface->i_flags & IFACE_CONFIG ) {
736 putc( 'C', rtmpdebug );
738 if ( iface->i_flags & IFACE_NOROUTER ) {
739 putc( 'N', rtmpdebug );
741 if ( iface->i_flags & IFACE_LOOP ) {
742 putc( 'L', rtmpdebug );
744 putc( '\n', rtmpdebug );
747 fprintf( rtmpdebug, "\t%u-%u ",
748 ntohs( iface->i_rt->rt_firstnet ),
749 ntohs( iface->i_rt->rt_lastnet ));
750 if ( iface->i_rt->rt_flags & RTMPTAB_ZIPQUERY ) {
751 putc( 'q', rtmpdebug );
753 if ( iface->i_rt->rt_flags & RTMPTAB_HASZONES ) {
754 putc( 'z', rtmpdebug );
756 if ( iface->i_rt->rt_flags & RTMPTAB_EXTENDED ) {
757 putc( 'x', rtmpdebug );
759 putc( 'i', rtmpdebug );
760 for ( l = iface->i_rt->rt_zt; l; l = l->l_next ) {
761 zt = (struct ziptab *)l->l_data;
762 fprintf( rtmpdebug, " '%.*s'", zt->zt_len, zt->zt_name );
764 fprintf( rtmpdebug, "\n" );
767 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
768 fprintf( rtmpdebug, "gate %u.%u %X\n",
769 ntohs( gate->g_sat.sat_addr.s_net ),
770 gate->g_sat.sat_addr.s_node, gate->g_state );
771 for ( rt = gate->g_rt; rt; rt = rt->rt_next ) {
772 fprintf( rtmpdebug, "\t%u-%u ", ntohs( rt->rt_firstnet ),
773 ntohs( rt->rt_lastnet ));
774 if ( rt->rt_flags & RTMPTAB_ZIPQUERY ) {
775 putc( 'q', rtmpdebug );
777 if ( rt->rt_flags & RTMPTAB_HASZONES ) {
778 putc( 'z', rtmpdebug );
780 if ( rt->rt_flags & RTMPTAB_EXTENDED ) {
781 putc( 'x', rtmpdebug );
783 if ( rt->rt_iprev ) {
784 putc( 'i', rtmpdebug );
786 for ( l = rt->rt_zt; l; l = l->l_next ) {
787 zt = (struct ziptab *)l->l_data;
788 fprintf( rtmpdebug, " '%.*s'", zt->zt_len, zt->zt_name );
790 fprintf( rtmpdebug, "\n" );
799 * Called when SIGTERM is recieved. Remove all routes and then exit.
801 #if !defined( ibm032 ) && !defined( _IBMR2 )
803 #endif /* ! ibm032 && ! _IBMR2 */
806 struct interface *iface;
810 for ( iface = interfaces; iface; iface = iface->i_next ) {
811 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
812 for ( rt = gate->g_rt; rt; rt = rt->rt_next ) {
813 if ( rt->rt_iprev ) {
814 if ( gateroute( RTMP_DEL, rt ) < 0 ) {
815 syslog( LOG_ERR, "as_down remove %u-%u failed: %m",
816 ntohs( rt->rt_firstnet ),
817 ntohs( rt->rt_lastnet ));
822 if ( iface->i_flags & IFACE_LOOP ) {
823 if (looproute( iface, RTMP_DEL )) {
824 syslog( LOG_ERR, "as_down remove %s %u.%u failed: %m",
825 iface->i_name, ntohs( iface->i_addr.sat_addr.s_net ),
826 iface->i_addr.sat_addr.s_node );
831 syslog( LOG_INFO, "done" );
842 struct sockaddr_at sat;
845 struct interface *iface;
854 while (( c = getopt( ac, av, "12qsdtf:P:" )) != EOF ) {
857 defphase = IFACE_PHASE1;
861 defphase = IFACE_PHASE2;
872 case 'q' : /* don't seed */
876 case 's' : /* seed */
880 case 't' : /* transition */
884 case 'P' : /* pid file */
889 fprintf( stderr, "Unknown option -- '%c'\n", c );
893 if ( optind != ac ) {
894 fprintf( stderr, "Too many arguments.\n" );
898 if (( prog = strrchr( av[ 0 ], '/' )) == NULL ) {
905 * Configure loop back address first, so appearances of "lo0" in
906 * the config file fail. Also insures that lo0 gets configured,
907 * even if there's some hangup during configuration of some
910 if (( interfaces = newiface( LOOPIFACE )) == NULL ) {
911 perror( "newiface" );
914 interfaces->i_flags |= IFACE_PHASE2 | IFACE_LOOPBACK;
917 * Check our initial configuration before we fork. This way we can
918 * complain about syntax errors on stdout.
920 * Basically, if we're going to read our config file, we should read
921 * it and initialize our data structures. If we're not going to read
922 * our config file, use GIFCONF to initialize our data structures.
924 if ( readconf( configfile ) < 0 && getifconf() < 0 ) {
925 fprintf( stderr, "%s: can't get interfaces, exiting.\n", prog );
929 /* we need to count up our interfaces so that we can simplify things
930 * later. we also need to figure out if we have more than one interface
931 * that is routing. */
932 for (i = 0, ninterfaces = 0, iface = interfaces; iface;
933 iface=iface->i_next) {
934 if (iface->i_flags & IFACE_DONTROUTE)
938 i = ninterfaces - i; /* number of routable interfaces */
941 * At this point, we have (at least partially) initialized data
942 * structures. Fill in what we can and verify that nothing is obviously
945 for (iface = interfaces; iface; iface = iface->i_next) {
946 /* Apply the default phase */
947 if (( iface->i_flags & IFACE_PHASE1 ) == 0 &&
948 ( iface->i_flags & IFACE_PHASE2 ) == 0 ) {
949 iface->i_flags |= defphase;
952 /* set up router flag information. if we have multiple interfaces
953 * and DONTROUTE isn't set, set up ROUTER. i is the number of
954 * interfaces that don't have the DONTROUTE flag set. */
955 if ((i > IFBASE) && ((iface->i_flags & IFACE_DONTROUTE) == 0)) {
956 iface->i_flags |= IFACE_ISROUTER;
959 /* Set default addresses */
960 if ( iface->i_rt == NULL ) {
961 if (( iface->i_rt = newrt(iface)) == NULL ) {
966 if ( iface->i_flags & IFACE_PHASE1 ) {
967 iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet =
968 iface->i_caddr.sat_addr.s_net;
970 if ( iface->i_caddr.sat_addr.s_net != ATADDR_ANYNET ||
971 ( iface->i_flags & IFACE_LOOPBACK )) {
972 iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet =
973 iface->i_caddr.sat_addr.s_net;
975 iface->i_rt->rt_firstnet = htons( STARTUP_FIRSTNET );
976 iface->i_rt->rt_lastnet = htons( STARTUP_LASTNET );
981 if (( iface->i_flags & IFACE_PHASE1 ) == 0 ) {
982 iface->i_rt->rt_flags |= RTMPTAB_EXTENDED;
985 if ( iface->i_caddr.sat_addr.s_net == ATADDR_ANYNET ) {
986 iface->i_caddr.sat_addr.s_net = iface->i_rt->rt_firstnet;
990 dumpconfig( iface ); /* probably needs args */
995 * A little consistency check...
997 if ( ninterfaces < IFBASE ) {
998 fprintf( stderr, "%s: zero interfaces, exiting.\n", prog );
1002 /* do this here so that we can use ifconfig */
1004 if ( plumb() < 0 ) {
1005 fprintf(stderr, "can't establish STREAMS plumbing, exiting.\n" );
1008 #endif /* __svr4__ */
1010 /* delete pre-existing interface addresses. */
1012 for (iface = interfaces; iface; iface = iface->i_next) {
1013 if (ifconfig(iface->i_name, SIOCDIFADDR, &iface->i_addr)) {
1014 #ifdef SIOCATALKDIFADDR
1015 #if (SIOCDIFADDR != SIOCATALKDIFADDR)
1016 ifconfig(iface->i_name, SIOCATALKDIFADDR, &iface->i_addr);
1017 #endif /* SIOCDIFADDR != SIOCATALKDIFADDR */
1018 #endif /* SIOCATALKDIFADDR */
1021 #endif /* SIOCDIFADDR */
1024 * Disassociate. The child will send itself a signal when it is
1025 * stable. This indicates that other processes may begin using
1028 switch (i = server_lock("atalkd", pidfile, debug)) {
1033 default: /* parent */
1035 * Wait for the child to send itself a SIGSTOP, after which
1036 * we send it a SIGCONT and exit ourself.
1038 if ( wait3( &status, WUNTRACED, (struct rusage *)0 ) != i) {
1039 perror( "wait3" ); /* Child died? */
1042 if ( !WIFSTOPPED( status )) {
1043 fprintf( stderr, "AppleTalk not up! Check your syslog for the reason." );
1044 if ( WIFEXITED( status )) {
1045 fprintf( stderr, " Child exited with %d.\n",
1046 WEXITSTATUS( status ));
1048 fprintf( stderr, " Child died.\n" );
1052 if ( kill(i, SIGCONT ) < 0 ) {
1060 openlog( prog, LOG_PID );
1062 openlog( prog, LOG_PID, LOG_DAEMON );
1065 syslog( LOG_INFO, "restart (%s)", version );
1068 * Socket for use in routing ioctl()s. Can't add routes to our
1069 * interfaces until we have our routing socket.
1072 if (( rtfd = socket( PF_ROUTE, SOCK_RAW, AF_APPLETALK )) < 0 ) {
1073 syslog( LOG_ERR, "route socket: %m" );
1076 if ( shutdown( rtfd, 0 ) < 0 ) {
1077 syslog( LOG_ERR, "route shutdown: %m" );
1081 if (( rtfd = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1082 syslog( LOG_ERR, "route socket: %m" );
1087 memset(&sv, 0, sizeof(sv));
1088 sv.sa_handler = as_down;
1089 sigemptyset( &sv.sa_mask );
1090 sigaddset( &sv.sa_mask, SIGUSR1 );
1091 sigaddset( &sv.sa_mask, SIGALRM );
1092 sigaddset( &sv.sa_mask, SIGTERM );
1093 sv.sa_flags = SA_RESTART;
1094 if ( sigaction( SIGTERM, &sv, NULL) < 0 ) {
1095 syslog( LOG_ERR, "sigterm: %m" );
1099 sv.sa_handler = as_debug;
1100 sigemptyset( &sv.sa_mask );
1101 sigaddset( &sv.sa_mask, SIGUSR1 );
1102 sigaddset( &sv.sa_mask, SIGALRM );
1103 sigaddset( &sv.sa_mask, SIGTERM );
1104 sv.sa_flags = SA_RESTART;
1105 if ( sigaction( SIGUSR1, &sv, NULL) < 0 ) {
1106 syslog( LOG_ERR, "sigusr1: %m" );
1110 sv.sa_handler = as_timer;
1111 sigemptyset( &sv.sa_mask );
1112 sigaddset( &sv.sa_mask, SIGUSR1 );
1113 sigaddset( &sv.sa_mask, SIGALRM );
1114 sigaddset( &sv.sa_mask, SIGTERM );
1115 sv.sa_flags = SA_RESTART;
1116 if ( sigaction( SIGALRM, &sv, NULL) < 0 ) {
1117 syslog( LOG_ERR, "sigalrm: %m" );
1121 it.it_interval.tv_sec = 10L;
1122 it.it_interval.tv_usec = 0L;
1123 it.it_value.tv_sec = 10L;
1124 it.it_value.tv_usec = 0L;
1125 if ( setitimer( ITIMER_REAL, &it, NULL) < 0 ) {
1126 syslog( LOG_ERR, "setitimer: %m" );
1130 ciface = interfaces;
1134 if ( select( nfds, &readfds, NULL, NULL, NULL) < 0 ) {
1135 if ( errno == EINTR ) {
1139 syslog( LOG_ERR, "select: %m" );
1144 for ( iface = interfaces; iface; iface = iface->i_next ) {
1145 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1146 if ( FD_ISSET( ap->ap_fd, &readfds )) {
1147 if ( ap->ap_packet ) {
1148 fromlen = sizeof( struct sockaddr_at );
1149 if (( c = recvfrom( ap->ap_fd, Packet, sizeof( Packet ),
1150 0, (struct sockaddr *)&sat, &fromlen )) < 0 ) {
1151 syslog( LOG_ERR, "recvfrom: %m" );
1156 printf( "packet from %u.%u on %s (%x) %d (%d)\n",
1157 ntohs( sat.sat_addr.s_net ),
1158 sat.sat_addr.s_node, iface->i_name,
1159 iface->i_flags, ap->ap_port, ap->ap_fd );
1160 bprint( Packet, c );
1164 if ( sighold( SIGALRM ) || sighold( SIGUSR1 )) {
1165 syslog( LOG_ERR, "sighold: %m" );
1168 #else /* __svr4__ */
1169 mask = sigsetmask( sigmask( SIGALRM ) |
1170 sigmask( SIGUSR1 ));
1171 #endif /* __svr4__ */
1172 if (( *ap->ap_packet )( ap, &sat, Packet, c ) < 0) {
1173 syslog(LOG_ERR, "ap->ap_packet: %m");
1181 if ( sigrelse( SIGUSR1 ) || sigrelse( SIGALRM )) {
1182 syslog( LOG_ERR, "sigrelse: %m" );
1185 #else /* __svr4__ */
1187 #endif /* __svr4__ */
1196 * This code is called (from main(), as_timer(), zip_packet(),
1197 * and rtmp_packet()) to set the initial "bootstrapping" address
1200 void bootaddr( iface )
1201 struct interface *iface;
1208 if ( iface->i_flags & IFACE_ADDR ) {
1209 syslog( LOG_ERR, "bootaddr OOPS!" );
1213 if ( iface->i_flags & IFACE_PHASE1 ) {
1214 setaddr( iface, IFACE_PHASE1, 0,
1215 iface->i_caddr.sat_addr.s_node, 0, 0 );
1217 if ( iface->i_flags & IFACE_LOOPBACK ) {
1218 iface->i_flags |= IFACE_CONFIG | IFACE_ADDR;
1219 if ( ciface == iface ) {
1220 ciface = ciface->i_next;
1224 } else if (rtmp_request( iface ) < 0) {
1225 syslog(LOG_ERR, "bootaddr (rtmp_request): %m");
1230 setaddr( iface, IFACE_PHASE2, iface->i_caddr.sat_addr.s_net,
1231 iface->i_caddr.sat_addr.s_node,
1232 iface->i_rt->rt_firstnet, iface->i_rt->rt_lastnet );
1234 if ( iface->i_flags & IFACE_LOOPBACK ) {
1235 iface->i_flags |= IFACE_CONFIG | IFACE_ADDR;
1236 if ( ciface == iface ) {
1237 ciface = ciface->i_next;
1241 } else if (zip_getnetinfo( iface ) < 0) {
1242 syslog(LOG_ERR, "bootaddr (zip_getnetinfo): %m");
1247 iface->i_flags |= IFACE_ADDR;
1248 stabletimer = UNSTABLE;
1254 * to manage the i_ports field and the fds for select().
1256 void setaddr( iface, phase, net, node, first, last )
1257 struct interface *iface;
1261 u_int16_t first, last;
1267 struct sockaddr_at sat;
1270 if ( iface->i_ports == NULL ) { /* allocate port structures */
1271 for ( i = 0, as = atserv; i < atservNATSERV; i++, as++ ) {
1272 if (( se = getservbyname( as->as_name, "ddp" )) == NULL ) {
1273 syslog( LOG_INFO, "%s: service unknown", as->as_name );
1275 as->as_port = ntohs( se->s_port );
1277 if (( ap = (struct atport *)malloc( sizeof( struct atport ))) ==
1279 syslog( LOG_ERR, "malloc: %m" );
1283 ap->ap_next = iface->i_ports;
1284 ap->ap_iface = iface;
1285 ap->ap_port = as->as_port;
1286 ap->ap_packet = as->as_packet;
1288 iface->i_ports = ap;
1290 } else { /* close ports */
1291 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1292 (void)close( ap->ap_fd );
1297 iface->i_addr.sat_len = sizeof( struct sockaddr_at );
1299 iface->i_addr.sat_family = AF_APPLETALK;
1300 iface->i_addr.sat_addr.s_net = net;
1301 iface->i_addr.sat_addr.s_node = node;
1303 nr.nr_phase = phase;
1304 nr.nr_firstnet = first;
1305 nr.nr_lastnet = last;
1306 memcpy( iface->i_addr.sat_zero, &nr, sizeof( struct netrange ));
1308 if ( ifconfig( iface->i_name, SIOCSIFADDR, &iface->i_addr )) {
1309 syslog( LOG_ERR, "setifaddr: %s (%u-%u): %m. try specifying a \
1310 smaller net range.", iface->i_name, ntohs(first), ntohs(last));
1313 if ( ifconfig( iface->i_name, SIOCGIFADDR, &iface->i_addr )) {
1314 syslog( LOG_ERR, "getifaddr: %s: %m", iface->i_name );
1319 i = 1; /* enable broadcasts */
1321 syslog(LOG_INFO, "setsockopt incompatible w/ Solaris STREAMS module.");
1322 #endif /* __svr4__ */
1323 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1324 if (( ap->ap_fd = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1325 syslog( LOG_ERR, "socket: %m" );
1329 setsockopt(ap->ap_fd, SOL_SOCKET, SO_BROADCAST, &i, sizeof(i));
1330 #endif /* ! __svr4 */
1332 memset( &sat, 0, sizeof( struct sockaddr_at ));
1334 sat.sat_len = sizeof( struct sockaddr_at );
1336 sat.sat_family = AF_APPLETALK;
1337 sat.sat_addr.s_net = iface->i_addr.sat_addr.s_net;
1338 sat.sat_addr.s_node = iface->i_addr.sat_addr.s_node;
1339 sat.sat_port = ap->ap_port;
1341 if ( bind( ap->ap_fd, (struct sockaddr *)&sat,
1342 sizeof( struct sockaddr_at )) < 0 ) {
1343 syslog( LOG_ERR, "bind %u.%u:%u: %m",
1344 ntohs( sat.sat_addr.s_net ),
1345 sat.sat_addr.s_node, sat.sat_port );
1347 /* remove all interfaces if we have a problem with bind */
1348 for (iface = interfaces; iface; iface = iface->i_next) {
1349 if (ifconfig( iface->i_name, SIOCDIFADDR, &iface->i_addr )) {
1350 #ifdef SIOCATALKDIFADDR
1351 #if (SIOCDIFADDR != SIOCATALKDIFADDR)
1352 ifconfig( iface->i_name, SIOCATALKDIFADDR, &iface->i_addr );
1353 #endif /* SIOCDIFADDR != SIOCATALKDIFADDR */
1354 #endif /* SIOCATALKDIFADDR */
1357 #endif /* SIOCDIFADDR */
1362 /* recalculate nfds and fds */
1364 for ( nfds = 0, iface = interfaces; iface; iface = iface->i_next ) {
1365 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1366 FD_SET( ap->ap_fd, &fds );
1367 if ( ap->ap_fd > nfds ) {
1375 int ifconfig( iname, cmd, sa )
1378 struct sockaddr_at *sa;
1383 memset(&ifr, 0, sizeof(ifr));
1384 strcpy( ifr.ifr_name, iname );
1385 ifr.ifr_addr = *(struct sockaddr *)sa;
1387 if (( s = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1390 if ( ioctl( s, cmd, &ifr ) < 0 ) {
1395 if ( cmd == SIOCGIFADDR ) {
1396 *(struct sockaddr *)sa = ifr.ifr_addr;
1401 void dumpconfig( iface )
1402 struct interface *iface;
1406 printf( "%s", iface->i_name );
1407 if ( iface->i_flags & IFACE_RSEED ) {
1408 printf( " -router" );
1409 } else if ( iface->i_flags & IFACE_SEED ) {
1413 if ( iface->i_flags & IFACE_DONTROUTE)
1414 printf( " -dontroute");
1416 printf( " -phase" );
1417 if ( iface->i_flags & IFACE_PHASE1 ) {
1422 printf( " -net %d", ntohs( iface->i_rt->rt_firstnet ));
1423 if ( iface->i_rt->rt_lastnet != iface->i_rt->rt_firstnet ) {
1424 printf( "-%d", ntohs( iface->i_rt->rt_lastnet ));
1426 printf( " -addr %u.%u", ntohs( iface->i_addr.sat_addr.s_net ),
1427 iface->i_addr.sat_addr.s_node );
1428 printf( " -caddr %u.%u", ntohs( iface->i_caddr.sat_addr.s_net ),
1429 iface->i_caddr.sat_addr.s_node );
1430 for ( l = iface->i_rt->rt_zt; l; l = l->l_next ) {
1431 printf( " -zone %.*s", ((struct ziptab *)l->l_data)->zt_len,
1432 ((struct ziptab *)l->l_data)->zt_name );
1440 struct interface *iface;
1441 struct rtmptab *rtmp;
1445 for ( iface = interfaces; iface; iface = iface->i_next ) {
1446 for ( rtmp = iface->i_rt; rtmp; rtmp = rtmp->rt_inext ) {
1447 if ( rtmp->rt_gate == 0 ) {
1448 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
1449 printf( "%u-%u", ntohs( rtmp->rt_firstnet ),
1450 ntohs( rtmp->rt_lastnet ));
1452 printf( "%u", ntohs( rtmp->rt_firstnet ));
1455 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
1456 printf( "%u.%u for %u-%u",
1457 ntohs( rtmp->rt_gate->g_sat.sat_addr.s_net ),
1458 rtmp->rt_gate->g_sat.sat_addr.s_node,
1459 ntohs( rtmp->rt_firstnet ),
1460 ntohs( rtmp->rt_lastnet ));
1462 printf( "%u.%u for %u",
1463 ntohs( rtmp->rt_gate->g_sat.sat_addr.s_net ),
1464 rtmp->rt_gate->g_sat.sat_addr.s_node,
1465 ntohs( rtmp->rt_firstnet ));
1469 if ( rtmp->rt_iprev == 0 && rtmp != iface->i_rt ) {
1473 for ( l = rtmp->rt_zt; l; l = l->l_next ) {
1474 zt = (struct ziptab *)l->l_data;
1475 printf( " %.*s", zt->zt_len, zt->zt_name );
1488 struct interface *iface;
1489 struct rtmptab *rtmp;
1493 for ( zt = ziptab; zt; zt = zt->zt_next ) {
1494 printf( "%.*s", zt->zt_len, zt->zt_name );
1495 for ( l = zt->zt_rt; l; l = l->l_next ) {
1496 rtmp = (struct rtmptab *)l->l_data;
1497 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
1498 printf( " %u-%u", ntohs( rtmp->rt_firstnet ),
1499 ntohs( rtmp->rt_lastnet ));
1501 printf( " %u", ntohs( rtmp->rt_firstnet ));
1503 if ( rtmp->rt_iprev == 0 && rtmp->rt_gate != 0 ) {