2 * Copyright (c) 1990,1993 Regents of The University of Michigan.
3 * All Rights Reserved. See COPYRIGHT.
10 #include <sys/types.h>
11 #include <sys/param.h>
12 #include <sys/socket.h>
13 #if defined( sun ) && defined( __svr4__ )
14 #include </usr/ucbinclude/sys/file.h>
19 #include <sys/resource.h>
20 #include <sys/ioctl.h>
24 #include <net/route.h>
35 #include <netatalk/endian.h>
36 #include <netatalk/at.h>
37 #include <atalk/compat.h>
38 #include <atalk/zip.h>
39 #include <atalk/rtmp.h>
40 #include <atalk/ddp.h>
41 #include <atalk/atp.h>
42 #include <atalk/paths.h>
43 #include <atalk/util.h>
46 #include <sys/sockio.h>
50 #include "interface.h"
58 /* Forward Declarations */
59 int ifconfig(const char *iname, unsigned long cmd, struct sockaddr_at *sa);
61 /* FIXME/SOCKLEN_T: socklen_t is a unix98 feature */
63 #define SOCKLEN_T unsigned int
67 #define WEXITSTATUS(x) ((x).w_retcode)
70 /* linux has a special ioctl for appletalk device destruction. as of
71 * 2.1.57, SIOCDIFADDR works w/ linux. okay, we need to deal with the
72 * fact that SIOCDIFADDR may be defined on linux despite the fact that
74 #if !defined(SIOCDIFADDR) && defined(SIOCATALKDIFADDR)
75 #define SIOCDIFADDR SIOCATALKDIFADDR
78 #define elements(a) (sizeof(a)/sizeof((a)[0]))
82 extern int rtmp_packet();
83 extern int nbp_packet();
84 extern int aep_packet();
85 extern int zip_packet();
89 struct atserv atserv[] = {
90 { "rtmp", 1, rtmp_packet }, /* 0 */
91 { "nbp", 2, nbp_packet }, /* 1 */
92 { "echo", 4, aep_packet }, /* 2 */
93 { "zip", 6, zip_packet }, /* 3 */
95 int atservNATSERV = elements( atserv );
97 struct interface *interfaces = NULL, *ciface = NULL;
99 int debug = 0, quiet = 0, chatty = 0;
100 char *configfile = NULL;
101 int ziptimeout = 0, transition = 0;
102 int stabletimer, stable = 0, newrtmpdata = 0, noparent = 0;
103 static int ninterfaces;
104 int defphase = IFACE_PHASE2;
107 char Packet[ PKTSZ ];
108 char *version = VERSION;
109 static char *pidfile = _PATH_ATALKDLOCK;
114 int readconf( char * );
115 int getifconf( void );
116 int writeconf( char * );
118 /* this is the messiest of the bunch as atalkd can exit pretty much
119 * everywhere. we delete interfaces here instead of in as_down. */
120 static void atalkd_exit(const int i)
123 struct interface *iface;
125 for (iface = interfaces; iface; iface = iface->i_next) {
126 if (ifconfig( iface->i_name, SIOCDIFADDR, &iface->i_addr)) {
127 #ifdef SIOCATALKDIFADDR
128 #if (SIOCDIFADDR != SIOCATALKDIFADDR)
129 if (!ifconfig(iface->i_name, SIOCATALKDIFADDR, &iface->i_addr))
133 syslog( LOG_ERR, "difaddr(%u.%u): %m",
134 ntohs(iface->i_addr.sat_addr.s_net),
135 iface->i_addr.sat_addr.s_node);
140 server_unlock(pidfile);
145 #if !defined( ibm032 ) && !defined( _IBMR2 )
150 struct sockaddr_at sat;
153 struct rtmp_tuple rt;
154 struct atport *ap, *zap, *rap;
155 struct interface *iface, *iface2;
156 struct gate *gate, *fgate = NULL;
157 struct rtmptab *rtmp, *frtmp;
159 char *data, *end, packet[ ATP_BUFSIZ ];
163 memset(&sat, 0, sizeof( struct sockaddr_at ));
164 for ( iface = interfaces; iface; iface = iface->i_next ) {
165 if ( iface->i_flags & IFACE_LOOPBACK ) {
168 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
169 if ( ap->ap_packet == zip_packet ) {
172 if ( ap->ap_packet == rtmp_packet ) {
177 if (( iface->i_flags & ( IFACE_ADDR|IFACE_CONFIG|IFACE_NOROUTER )) ==
179 if ( iface->i_time < 3 ) {
180 if ( iface->i_flags & IFACE_PHASE1 ) {
181 if (rtmp_request( iface ) < 0) {
182 syslog(LOG_ERR, "rtmp_request: %m");
187 if (zip_getnetinfo( iface ) < 0) {
188 syslog(LOG_ERR, "zip_getnetinfo: %m");
195 iface->i_flags |= IFACE_NOROUTER;
196 if ((iface->i_flags & IFACE_ISROUTER)) {
197 if (( iface->i_flags & IFACE_SEED ) == 0 ) {
199 * No seed info, and we've got multiple interfaces.
203 "as_timer multiple interfaces, no seed" );
204 syslog( LOG_INFO, "as_timer can't configure %s",
206 syslog( LOG_INFO, "as_timer waiting for router" );
211 * Complete configuration for iface, and boot next
214 iface->i_flags |= IFACE_CONFIG;
215 for ( zt = iface->i_czt; zt; zt = zt->zt_next ) {
216 if (addzone( iface->i_rt, zt->zt_len,
218 syslog(LOG_ERR, "addzone: %m");
222 if ( iface->i_rt->rt_zt ) {
223 iface->i_rt->rt_flags &= ~RTMPTAB_ZIPQUERY;
224 iface->i_rt->rt_flags |= RTMPTAB_HASZONES;
226 if ( iface->i_flags & IFACE_PHASE1 ) {
228 "as_timer configured %s phase 1 from seed",
230 setaddr( iface, IFACE_PHASE1,
231 iface->i_caddr.sat_addr.s_net,
232 iface->i_addr.sat_addr.s_node,
233 iface->i_caddr.sat_addr.s_net,
234 iface->i_caddr.sat_addr.s_net );
237 "as_timer configured %s phase 2 from seed",
241 if ( looproute( iface, RTMP_ADD )) { /* -1 or 1 */
243 "as_timer: can't route %u.%u to loop: %m",
244 ntohs( iface->i_addr.sat_addr.s_net ),
245 iface->i_addr.sat_addr.s_node );
248 if ( iface == ciface ) {
249 ciface = ciface->i_next;
255 * Configure for no router operation. Wait for a route
256 * to become available in rtmp_packet().
258 syslog( LOG_INFO, "config for no router" );
260 if ( iface->i_flags & IFACE_PHASE2 ) {
261 iface->i_rt->rt_firstnet = 0;
262 iface->i_rt->rt_lastnet = htons( STARTUP_LASTNET );
263 setaddr( iface, IFACE_PHASE2,
264 iface->i_addr.sat_addr.s_net,
265 iface->i_addr.sat_addr.s_node,
266 0, htons( STARTUP_LASTNET ));
268 if ( looproute( iface, RTMP_ADD ) ) { /* -1 or 1 */
270 "as_timer: can't route %u.%u to loopback: %m",
271 ntohs( iface->i_addr.sat_addr.s_net ),
272 iface->i_addr.sat_addr.s_node );
276 if ( iface == ciface ) {
277 ciface = ciface->i_next;
284 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
286 free( (caddr_t)fgate );
291 data = packet + 1 + sizeof( struct ziphdr );
292 end = packet + sizeof( packet );
295 sat.sat_port = zap->ap_port;
298 * Perform timeouts on routers. If we've only got one
299 * interface, we'll use these timeouts to decide that
300 * our zone has gone away.
302 if ( ++gate->g_state >= RTMPTAB_BAD ) {
303 syslog( LOG_INFO, "as_timer gateway %u.%u down",
304 ntohs( gate->g_sat.sat_addr.s_net ),
305 gate->g_sat.sat_addr.s_node );
308 frtmp = rtmp->rt_next;
309 if ( rtmp->rt_hops == RTMPHOPS_POISON ||
310 rtmp->rt_iprev == 0 ) {
313 rtmp->rt_hops = RTMPHOPS_POISON;
314 if ((cc = rtmp_replace( rtmp )) < 0) {
315 syslog(LOG_ERR, "rtmp_replace: %m");
319 gate->g_state = rtmp->rt_state = RTMPTAB_GOOD;
324 if ( gate->g_rt == 0 ) {
325 if ( gate->g_prev == 0 ) {
326 gate->g_iface->i_gate = gate->g_next;
328 gate->g_prev->g_next = gate->g_next;
330 if ( gate->g_next != 0 ) {
331 gate->g_next->g_prev = gate->g_prev;
333 fgate = gate; /* can't free here, just mark it */
336 * If this is the last router on the only interface,
337 * reconfigure our netrange. By marking the interface
338 * as having no router, we will notice when a router
341 * XXX: actually, we always reconfigure an interface
342 * if we're not a seed router.
345 if ( gate->g_iface->i_gate == 0 &&
346 ((iface->i_flags & IFACE_SEED) == 0)) {
347 gate->g_iface->i_flags |= IFACE_NOROUTER;
348 gate->g_iface->i_flags &= ~IFACE_CONFIG;
350 /* get rid of any zones associated with this iface */
351 if (gate->g_iface->i_rt->rt_zt) {
352 rtmp_delzonemap(gate->g_iface->i_rt);
353 gate->g_iface->i_rt->rt_flags &= ~RTMPTAB_HASZONES;
356 syslog( LOG_INFO, "as_timer last gateway down" );
358 /* Set netrange to 0-fffe. */
359 if ( gate->g_iface->i_flags & IFACE_PHASE2 ) {
360 gate->g_iface->i_rt->rt_firstnet = 0;
361 gate->g_iface->i_rt->rt_lastnet =
362 htons( STARTUP_LASTNET );
363 setaddr( iface, IFACE_PHASE2,
364 iface->i_addr.sat_addr.s_net,
365 iface->i_addr.sat_addr.s_node,
366 0, htons( STARTUP_LASTNET ));
373 * If we don't have a zone for our interface yet, ask for
374 * it from any router (all routers) on the interface.
376 if (( iface->i_rt->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
377 iface->i_rt->rt_flags |= RTMPTAB_ZIPQUERY;
378 memcpy( data, &iface->i_rt->rt_firstnet, sizeof( u_short ));
379 data += sizeof( u_short );
386 * Delete old routing tuples.
388 if ( rtmp->rt_state != RTMPTAB_PERM ) {
393 * We've not been updated for this route in a while. If
394 * it's not in use, go ahead and remove it. If it is in
395 * use, mark the route as down (POISON), and look for a
396 * better route. If one is found, delete this route and use
397 * the new one. If it's not found, mark the route as GOOD
398 * (so we'll propogate our poison) and delete it the next
399 * time it becomes BAD.
401 if ( rtmp->rt_state >= RTMPTAB_BAD ) {
402 frtmp = rtmp->rt_next;
403 if ( rtmp->rt_iprev == 0 ) { /* not in use */
405 } else { /* in use */
406 if ( rtmp->rt_hops == RTMPHOPS_POISON ) {
409 rtmp->rt_hops = RTMPHOPS_POISON;
410 if ((cc = rtmp_replace( rtmp )) < 0) {
411 syslog(LOG_ERR, "rtmp_replace: %m");
415 rtmp->rt_state = RTMPTAB_GOOD;
425 if ( rtmp->rt_iprev &&
426 ( rtmp->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
427 if ( data + sizeof( u_short ) > end || n == 255 ) {
428 /* send what we've got */
429 zh.zh_op = ZIPOP_QUERY;
433 *data++ = DDPTYPE_ZIP;
434 memcpy( data, &zh, sizeof( struct ziphdr ));
436 if ( sendto( zap->ap_fd, packet, cc, 0,
437 (struct sockaddr *)&sat,
438 sizeof( struct sockaddr_at )) < 0 ) {
439 syslog( LOG_ERR, "as_timer sendto: %m" );
444 data = packet + 1 + sizeof( struct ziphdr );
445 end = packet + sizeof( packet );
449 * rt_nzq is number of ZIP Queries we've issued for a
450 * given netrange. If we've got ziptimeout on, we
451 * will only ask 3 times for any given netrange.
452 * Interestingly enough, since rt_nzq is a u_char,
453 * it will overflow after a while. This means we will
454 * periodically ask for nets that we've decided not to
455 * ask about, and warn that we can't get it's zone.
457 if ( rtmp->rt_nzq++ == 3 ) {
458 syslog( LOG_INFO, "as_timer can't get zone for %u",
459 ntohs( rtmp->rt_firstnet ));
461 if ( rtmp->rt_nzq > 3 ) {
463 rtmp = rtmp->rt_next;
469 rtmp->rt_flags |= RTMPTAB_ZIPQUERY;
470 memcpy( data, &rtmp->rt_firstnet, sizeof( u_short ));
471 data += sizeof( u_short );
474 rtmp = rtmp->rt_next;
477 /* send what we've got */
479 zh.zh_op = ZIPOP_QUERY;
483 *data++ = DDPTYPE_ZIP;
484 memcpy( data, &zh, sizeof( struct ziphdr ));
486 if ( sendto( zap->ap_fd, packet, cc, 0, (struct sockaddr *)&sat,
487 sizeof( struct sockaddr_at )) < 0 ) {
488 syslog( LOG_ERR, "as_timer sendto: %m" );
493 free( (caddr_t)fgate );
498 * Send RTMP broadcasts if we have multiple interfaces or our
499 * interface is configured as a router.
501 if ((iface->i_flags & IFACE_ISROUTER)) {
503 sat.sat_len = sizeof( struct sockaddr_at );
505 sat.sat_family = AF_APPLETALK;
506 sat.sat_addr.s_net = ATADDR_ANYNET;
507 sat.sat_addr.s_node = ATADDR_BCAST;
508 sat.sat_port = rap->ap_port;
511 end = data + sizeof( packet );
512 *data++ = DDPTYPE_RTMPRD;
513 rh.rh_net = iface->i_addr.sat_addr.s_net;
515 rh.rh_node = iface->i_addr.sat_addr.s_node;
516 memcpy( data, &rh, sizeof( struct rtmp_head ));
517 data += sizeof( struct rtmp_head );
521 if ( iface->i_flags & IFACE_PHASE1 ) {
524 memcpy( data, &rt, SZ_RTMPTUPLE );
525 data += SZ_RTMPTUPLE;
527 rt.rt_net = iface->i_rt->rt_firstnet;
529 memcpy( data, &rt, SZ_RTMPTUPLE );
530 data += SZ_RTMPTUPLE;
532 rt.rt_net = iface->i_rt->rt_lastnet;
534 memcpy( data, &rt, SZ_RTMPTUPLE );
535 data += SZ_RTMPTUPLE;
538 for ( iface2 = interfaces; iface2; iface2 = iface2->i_next ) {
540 /* XXX: there used to be a bit checking against iface ==
541 iface2. also, we don't want to send an rtmp broadcast
542 to an interface that doesn't want it. */
543 if ((( iface2->i_flags & IFACE_CONFIG ) == 0) ||
544 ((iface2->i_flags & IFACE_ISROUTER) == 0)) {
548 * Fill in tuples. Always send the same thing, regardless
549 * of the phase of the destination. Routers who don't
550 * understand extended rtmp packets will toss extended
551 * tuples because their distance will have the high bit set.
553 for ( rtmp = iface2->i_rt; rtmp; rtmp = rtmp->rt_inext ) {
554 /* don't broadcast routes we have no zone for */
555 if ( rtmp->rt_zt == 0 ||
556 ( rtmp->rt_flags & RTMPTAB_ZIPQUERY ) ||
557 ( rtmp->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
561 if ((( rtmp->rt_flags & RTMPTAB_EXTENDED ) &&
562 data + 2 * SZ_RTMPTUPLE > end ) ||
563 data + SZ_RTMPTUPLE > end ) {
564 if ( sendto( rap->ap_fd, packet, data - packet, 0,
565 (struct sockaddr *)&sat,
566 sizeof( struct sockaddr_at )) < 0 ) {
567 syslog( LOG_ERR, "as_timer sendto %u.%u (%u): %m",
568 ntohs( sat.sat_addr.s_net ),
570 ntohs( iface->i_rt->rt_firstnet ));
573 if ( iface->i_flags & IFACE_PHASE2 ) {
574 data = packet + 1 + sizeof( struct rtmp_head ) +
577 data = packet + 1 + sizeof( struct rtmp_head ) +
583 rt.rt_net = rtmp->rt_firstnet;
584 rt.rt_dist = rtmp->rt_hops;
585 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
588 memcpy( data, &rt, SZ_RTMPTUPLE );
589 data += SZ_RTMPTUPLE;
591 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
592 rt.rt_net = rtmp->rt_lastnet;
594 memcpy( data, &rt, SZ_RTMPTUPLE );
595 data += SZ_RTMPTUPLE;
603 if ( sendto( rap->ap_fd, packet, data - packet, 0,
604 (struct sockaddr *)&sat,
605 sizeof( struct sockaddr_at )) < 0 ) {
606 syslog( LOG_ERR, "as_timer sendto %u.%u (%u): %m",
607 ntohs( sat.sat_addr.s_net ),
609 ntohs( iface->i_rt->rt_firstnet ));
616 * Check if we're stable. Each time we configure an interface, we
617 * sent stabletimer to UNSTABLE. If stabletimer ever gets to
618 * STABLEANYWAY, we give up and decide to "be" stable anyway.
619 * Normally, we wait for stabletimer get <= STABLE with no new rtmp
620 * data and all zip data complete.
623 if ( stabletimer <= STABLE && !newrtmpdata && !sentzipq ) {
624 /* write out config file */
626 writeconf( configfile );
628 if ( stabletimer-- <= STABLEANYWAY ) {
634 if ( stable && !noparent ) {
636 syslog( LOG_INFO, "ready %d/%d/%d", stabletimer, newrtmpdata,
640 * Seems like we could get here more than once...
642 if ( kill( getpid(), SIGSTOP ) < 0 ) {
643 syslog( LOG_ERR, "as_timer: kill-self failed!" );
657 * Consistency check...
661 struct rtmptab *rtmp;
662 struct list *lr, *lz;
665 for ( zt = ziptab; zt; zt = zt->zt_next ) {
666 for ( lr = zt->zt_rt; lr; lr = lr->l_next ) {
667 rtmp = (struct rtmptab *)lr->l_data;
668 if ( rtmp->rt_iprev == 0 && rtmp->rt_gate != 0 ) {
669 syslog( LOG_ERR, "%.*s has %u-%u (unused)\n",
670 zt->zt_len, zt->zt_name, ntohs( rtmp->rt_firstnet ),
671 ntohs( rtmp->rt_lastnet ));
674 for ( lz = rtmp->rt_zt; lz; lz = lz->l_next ) {
675 if ( zt == (struct ziptab *)lz->l_data ) {
680 syslog( LOG_ERR, "no map from %u-%u to %.*s\n",
681 ntohs( rtmp->rt_firstnet ),
682 ntohs( rtmp->rt_lastnet ),
683 zt->zt_len, zt->zt_name );
691 #if !defined( ibm032 ) && !defined( _IBMR2 )
696 struct interface *iface;
703 if (( rtmpdebug = fopen( _PATH_ATALKDEBUG, "w" )) == NULL ) {
704 syslog( LOG_ERR, "rtmp: %m" );
707 for ( iface = interfaces; iface; iface = iface->i_next ) {
708 fprintf( rtmpdebug, "interface %s %u.%u ", iface->i_name,
709 ntohs( iface->i_addr.sat_addr.s_net ),
710 iface->i_addr.sat_addr.s_node );
711 if ( iface->i_flags & IFACE_PHASE1 ) {
712 putc( '1', rtmpdebug );
714 if ( iface->i_flags & IFACE_PHASE2 ) {
715 putc( '2', rtmpdebug );
717 if ( iface->i_flags & IFACE_RSEED ) {
718 putc( 'R', rtmpdebug );
720 if ( iface->i_flags & IFACE_SEED ) {
721 putc( 'S', rtmpdebug );
723 if ( iface->i_flags & IFACE_DONTROUTE ) {
724 putc( 'D', rtmpdebug );
726 if ( iface->i_flags & IFACE_ADDR ) {
727 putc( 'A', rtmpdebug );
729 if ( iface->i_flags & IFACE_CONFIG ) {
730 putc( 'C', rtmpdebug );
732 if ( iface->i_flags & IFACE_NOROUTER ) {
733 putc( 'N', rtmpdebug );
735 if ( iface->i_flags & IFACE_LOOP ) {
736 putc( 'L', rtmpdebug );
738 putc( '\n', rtmpdebug );
741 fprintf( rtmpdebug, "\t%u-%u ",
742 ntohs( iface->i_rt->rt_firstnet ),
743 ntohs( iface->i_rt->rt_lastnet ));
744 if ( iface->i_rt->rt_flags & RTMPTAB_ZIPQUERY ) {
745 putc( 'q', rtmpdebug );
747 if ( iface->i_rt->rt_flags & RTMPTAB_HASZONES ) {
748 putc( 'z', rtmpdebug );
750 if ( iface->i_rt->rt_flags & RTMPTAB_EXTENDED ) {
751 putc( 'x', rtmpdebug );
753 putc( 'i', rtmpdebug );
754 for ( l = iface->i_rt->rt_zt; l; l = l->l_next ) {
755 zt = (struct ziptab *)l->l_data;
756 fprintf( rtmpdebug, " '%.*s'", zt->zt_len, zt->zt_name );
758 fprintf( rtmpdebug, "\n" );
761 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
762 fprintf( rtmpdebug, "gate %u.%u %X\n",
763 ntohs( gate->g_sat.sat_addr.s_net ),
764 gate->g_sat.sat_addr.s_node, gate->g_state );
765 for ( rt = gate->g_rt; rt; rt = rt->rt_next ) {
766 fprintf( rtmpdebug, "\t%u-%u ", ntohs( rt->rt_firstnet ),
767 ntohs( rt->rt_lastnet ));
768 if ( rt->rt_flags & RTMPTAB_ZIPQUERY ) {
769 putc( 'q', rtmpdebug );
771 if ( rt->rt_flags & RTMPTAB_HASZONES ) {
772 putc( 'z', rtmpdebug );
774 if ( rt->rt_flags & RTMPTAB_EXTENDED ) {
775 putc( 'x', rtmpdebug );
777 if ( rt->rt_iprev ) {
778 putc( 'i', rtmpdebug );
780 for ( l = rt->rt_zt; l; l = l->l_next ) {
781 zt = (struct ziptab *)l->l_data;
782 fprintf( rtmpdebug, " '%.*s'", zt->zt_len, zt->zt_name );
784 fprintf( rtmpdebug, "\n" );
793 * Called when SIGTERM is recieved. Remove all routes and then exit.
795 #if !defined( ibm032 ) && !defined( _IBMR2 )
800 struct interface *iface;
804 for ( iface = interfaces; iface; iface = iface->i_next ) {
805 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
806 for ( rt = gate->g_rt; rt; rt = rt->rt_next ) {
807 if ( rt->rt_iprev ) {
808 if ( gateroute( RTMP_DEL, rt ) < 0 ) {
809 syslog( LOG_ERR, "as_down remove %u-%u failed: %m",
810 ntohs( rt->rt_firstnet ),
811 ntohs( rt->rt_lastnet ));
816 if ( iface->i_flags & IFACE_LOOP ) {
817 if (looproute( iface, RTMP_DEL )) {
818 syslog( LOG_ERR, "as_down remove %s %u.%u failed: %m",
819 iface->i_name, ntohs( iface->i_addr.sat_addr.s_net ),
820 iface->i_addr.sat_addr.s_node );
825 syslog( LOG_INFO, "done" );
836 struct sockaddr_at sat;
839 struct interface *iface;
848 while (( c = getopt( ac, av, "12qsdtf:P:" )) != EOF ) {
851 defphase = IFACE_PHASE1;
855 defphase = IFACE_PHASE2;
866 case 'q' : /* don't seed */
870 case 's' : /* seed */
874 case 't' : /* transition */
878 case 'P' : /* pid file */
883 fprintf( stderr, "Unknown option -- '%c'\n", c );
887 if ( optind != ac ) {
888 fprintf( stderr, "Too many arguments.\n" );
892 if (( prog = strrchr( av[ 0 ], '/' )) == NULL ) {
899 * Configure loop back address first, so appearances of "lo0" in
900 * the config file fail. Also insures that lo0 gets configured,
901 * even if there's some hangup during configuration of some
904 if (( interfaces = newiface( LOOPIFACE )) == NULL ) {
905 perror( "newiface" );
908 interfaces->i_flags |= IFACE_PHASE2 | IFACE_LOOPBACK;
911 * Check our initial configuration before we fork. This way we can
912 * complain about syntax errors on stdout.
914 * Basically, if we're going to read our config file, we should read
915 * it and initialize our data structures. If we're not going to read
916 * our config file, use GIFCONF to initialize our data structures.
918 if ( readconf( configfile ) < 0 && getifconf() < 0 ) {
919 fprintf( stderr, "%s: can't get interfaces, exiting.\n", prog );
923 /* we need to count up our interfaces so that we can simplify things
924 * later. we also need to figure out if we have more than one interface
925 * that is routing. */
926 for (i = 0, ninterfaces = 0, iface = interfaces; iface;
927 iface=iface->i_next) {
928 if (iface->i_flags & IFACE_DONTROUTE)
932 i = ninterfaces - i; /* number of routable interfaces */
935 * At this point, we have (at least partially) initialized data
936 * structures. Fill in what we can and verify that nothing is obviously
939 for (iface = interfaces; iface; iface = iface->i_next) {
940 /* Apply the default phase */
941 if (( iface->i_flags & IFACE_PHASE1 ) == 0 &&
942 ( iface->i_flags & IFACE_PHASE2 ) == 0 ) {
943 iface->i_flags |= defphase;
946 /* set up router flag information. if we have multiple interfaces
947 * and DONTROUTE isn't set, set up ROUTER. i is the number of
948 * interfaces that don't have the DONTROUTE flag set. */
949 if ((i > IFBASE) && ((iface->i_flags & IFACE_DONTROUTE) == 0)) {
950 iface->i_flags |= IFACE_ISROUTER;
953 /* Set default addresses */
954 if ( iface->i_rt == NULL ) {
955 if (( iface->i_rt = newrt(iface)) == NULL ) {
960 if ( iface->i_flags & IFACE_PHASE1 ) {
961 iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet =
962 iface->i_caddr.sat_addr.s_net;
964 if ( iface->i_caddr.sat_addr.s_net != ATADDR_ANYNET ||
965 ( iface->i_flags & IFACE_LOOPBACK )) {
966 iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet =
967 iface->i_caddr.sat_addr.s_net;
969 iface->i_rt->rt_firstnet = htons( STARTUP_FIRSTNET );
970 iface->i_rt->rt_lastnet = htons( STARTUP_LASTNET );
975 if (( iface->i_flags & IFACE_PHASE1 ) == 0 ) {
976 iface->i_rt->rt_flags |= RTMPTAB_EXTENDED;
979 if ( iface->i_caddr.sat_addr.s_net == ATADDR_ANYNET ) {
980 iface->i_caddr.sat_addr.s_net = iface->i_rt->rt_firstnet;
984 dumpconfig( iface ); /* probably needs args */
989 * A little consistency check...
991 if ( ninterfaces < IFBASE ) {
992 fprintf( stderr, "%s: zero interfaces, exiting.\n", prog );
996 /* do this here so that we can use ifconfig */
999 fprintf(stderr, "can't establish STREAMS plumbing, exiting.\n" );
1004 /* delete pre-existing interface addresses. */
1006 for (iface = interfaces; iface; iface = iface->i_next) {
1007 if (ifconfig(iface->i_name, SIOCDIFADDR, &iface->i_addr)) {
1008 #ifdef SIOCATALKDIFADDR
1009 #if (SIOCDIFADDR != SIOCATALKDIFADDR)
1010 ifconfig(iface->i_name, SIOCATALKDIFADDR, &iface->i_addr);
1018 * Disassociate. The child will send itself a signal when it is
1019 * stable. This indicates that other processes may begin using
1022 switch (i = server_lock("atalkd", pidfile, debug)) {
1027 default: /* parent */
1029 * Wait for the child to send itself a SIGSTOP, after which
1030 * we send it a SIGCONT and exit ourself.
1032 if ( wait3( &status, WUNTRACED, (struct rusage *)0 ) != i) {
1033 perror( "wait3" ); /* Child died? */
1036 if ( !WIFSTOPPED( status )) {
1037 fprintf( stderr, "AppleTalk not up! Check your syslog for the reason." );
1038 if ( WIFEXITED( status )) {
1039 fprintf( stderr, " Child exited with %d.\n",
1040 WEXITSTATUS( status ));
1042 fprintf( stderr, " Child died.\n" );
1046 if ( kill(i, SIGCONT ) < 0 ) {
1054 openlog( prog, LOG_PID );
1056 openlog( prog, LOG_PID, LOG_DAEMON );
1059 syslog( LOG_INFO, "restart (%s)", version );
1062 * Socket for use in routing ioctl()s. Can't add routes to our
1063 * interfaces until we have our routing socket.
1066 if (( rtfd = socket( PF_ROUTE, SOCK_RAW, AF_APPLETALK )) < 0 ) {
1067 syslog( LOG_ERR, "route socket: %m" );
1070 if ( shutdown( rtfd, 0 ) < 0 ) {
1071 syslog( LOG_ERR, "route shutdown: %m" );
1075 if (( rtfd = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1076 syslog( LOG_ERR, "route socket: %m" );
1081 memset(&sv, 0, sizeof(sv));
1082 sv.sa_handler = as_down;
1083 sigemptyset( &sv.sa_mask );
1084 sigaddset( &sv.sa_mask, SIGUSR1 );
1085 sigaddset( &sv.sa_mask, SIGALRM );
1086 sigaddset( &sv.sa_mask, SIGTERM );
1087 sv.sa_flags = SA_RESTART;
1088 if ( sigaction( SIGTERM, &sv, NULL) < 0 ) {
1089 syslog( LOG_ERR, "sigterm: %m" );
1093 sv.sa_handler = as_debug;
1094 sigemptyset( &sv.sa_mask );
1095 sigaddset( &sv.sa_mask, SIGUSR1 );
1096 sigaddset( &sv.sa_mask, SIGALRM );
1097 sigaddset( &sv.sa_mask, SIGTERM );
1098 sv.sa_flags = SA_RESTART;
1099 if ( sigaction( SIGUSR1, &sv, NULL) < 0 ) {
1100 syslog( LOG_ERR, "sigusr1: %m" );
1104 sv.sa_handler = as_timer;
1105 sigemptyset( &sv.sa_mask );
1106 sigaddset( &sv.sa_mask, SIGUSR1 );
1107 sigaddset( &sv.sa_mask, SIGALRM );
1108 sigaddset( &sv.sa_mask, SIGTERM );
1109 sv.sa_flags = SA_RESTART;
1110 if ( sigaction( SIGALRM, &sv, NULL) < 0 ) {
1111 syslog( LOG_ERR, "sigalrm: %m" );
1115 it.it_interval.tv_sec = 10L;
1116 it.it_interval.tv_usec = 0L;
1117 it.it_value.tv_sec = 10L;
1118 it.it_value.tv_usec = 0L;
1119 if ( setitimer( ITIMER_REAL, &it, NULL) < 0 ) {
1120 syslog( LOG_ERR, "setitimer: %m" );
1124 ciface = interfaces;
1128 if ( select( nfds, &readfds, NULL, NULL, NULL) < 0 ) {
1129 if ( errno == EINTR ) {
1133 syslog( LOG_ERR, "select: %m" );
1138 for ( iface = interfaces; iface; iface = iface->i_next ) {
1139 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1140 if ( FD_ISSET( ap->ap_fd, &readfds )) {
1141 if ( ap->ap_packet ) {
1142 fromlen = sizeof( struct sockaddr_at );
1143 if (( c = recvfrom( ap->ap_fd, Packet, sizeof( Packet ),
1144 0, (struct sockaddr *)&sat, &fromlen )) < 0 ) {
1145 syslog( LOG_ERR, "recvfrom: %m" );
1150 printf( "packet from %u.%u on %s (%x) %d (%d)\n",
1151 ntohs( sat.sat_addr.s_net ),
1152 sat.sat_addr.s_node, iface->i_name,
1153 iface->i_flags, ap->ap_port, ap->ap_fd );
1154 bprint( Packet, c );
1158 if ( sighold( SIGALRM ) || sighold( SIGUSR1 )) {
1159 syslog( LOG_ERR, "sighold: %m" );
1163 mask = sigsetmask( sigmask( SIGALRM ) |
1164 sigmask( SIGUSR1 ));
1166 if (( *ap->ap_packet )( ap, &sat, Packet, c ) < 0) {
1167 syslog(LOG_ERR, "ap->ap_packet: %m");
1175 if ( sigrelse( SIGUSR1 ) || sigrelse( SIGALRM )) {
1176 syslog( LOG_ERR, "sigrelse: %m" );
1190 * This code is called (from main(), as_timer(), zip_packet(),
1191 * and rtmp_packet()) to set the initial "bootstrapping" address
1194 void bootaddr( iface )
1195 struct interface *iface;
1202 if ( iface->i_flags & IFACE_ADDR ) {
1203 syslog( LOG_ERR, "bootaddr OOPS!" );
1207 if ( iface->i_flags & IFACE_PHASE1 ) {
1208 setaddr( iface, IFACE_PHASE1, 0,
1209 iface->i_caddr.sat_addr.s_node, 0, 0 );
1211 if ( iface->i_flags & IFACE_LOOPBACK ) {
1212 iface->i_flags |= IFACE_CONFIG | IFACE_ADDR;
1213 if ( ciface == iface ) {
1214 ciface = ciface->i_next;
1218 } else if (rtmp_request( iface ) < 0) {
1219 syslog(LOG_ERR, "bootaddr (rtmp_request): %m");
1224 setaddr( iface, IFACE_PHASE2, iface->i_caddr.sat_addr.s_net,
1225 iface->i_caddr.sat_addr.s_node,
1226 iface->i_rt->rt_firstnet, iface->i_rt->rt_lastnet );
1228 if ( iface->i_flags & IFACE_LOOPBACK ) {
1229 iface->i_flags |= IFACE_CONFIG | IFACE_ADDR;
1230 if ( ciface == iface ) {
1231 ciface = ciface->i_next;
1235 } else if (zip_getnetinfo( iface ) < 0) {
1236 syslog(LOG_ERR, "bootaddr (zip_getnetinfo): %m");
1241 iface->i_flags |= IFACE_ADDR;
1242 stabletimer = UNSTABLE;
1248 * to manage the i_ports field and the fds for select().
1250 void setaddr( iface, phase, net, node, first, last )
1251 struct interface *iface;
1255 u_int16_t first, last;
1261 struct sockaddr_at sat;
1264 if ( iface->i_ports == NULL ) { /* allocate port structures */
1265 for ( i = 0, as = atserv; i < atservNATSERV; i++, as++ ) {
1266 if (( se = getservbyname( as->as_name, "ddp" )) == NULL ) {
1267 syslog( LOG_INFO, "%s: service unknown", as->as_name );
1269 as->as_port = ntohs( se->s_port );
1271 if (( ap = (struct atport *)malloc( sizeof( struct atport ))) ==
1273 syslog( LOG_ERR, "malloc: %m" );
1277 ap->ap_next = iface->i_ports;
1278 ap->ap_iface = iface;
1279 ap->ap_port = as->as_port;
1280 ap->ap_packet = as->as_packet;
1282 iface->i_ports = ap;
1284 } else { /* close ports */
1285 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1286 (void)close( ap->ap_fd );
1291 iface->i_addr.sat_len = sizeof( struct sockaddr_at );
1293 iface->i_addr.sat_family = AF_APPLETALK;
1294 iface->i_addr.sat_addr.s_net = net;
1295 iface->i_addr.sat_addr.s_node = node;
1297 nr.nr_phase = phase;
1298 nr.nr_firstnet = first;
1299 nr.nr_lastnet = last;
1300 memcpy( iface->i_addr.sat_zero, &nr, sizeof( struct netrange ));
1302 if ( ifconfig( iface->i_name, SIOCSIFADDR, &iface->i_addr )) {
1303 syslog( LOG_ERR, "setifaddr: %s (%u-%u): %m. try specifying a \
1304 smaller net range.", iface->i_name, ntohs(first), ntohs(last));
1307 if ( ifconfig( iface->i_name, SIOCGIFADDR, &iface->i_addr )) {
1308 syslog( LOG_ERR, "getifaddr: %s: %m", iface->i_name );
1313 i = 1; /* enable broadcasts */
1314 #if defined(__svr4__)
1315 syslog(LOG_INFO, "setsockopt incompatible w/ Solaris STREAMS module.");
1317 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1318 if (( ap->ap_fd = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1319 syslog( LOG_ERR, "socket: %m" );
1322 #if !defined(__svr4__)
1323 setsockopt(ap->ap_fd, SOL_SOCKET, SO_BROADCAST, &i, sizeof(i));
1326 memset( &sat, 0, sizeof( struct sockaddr_at ));
1328 sat.sat_len = sizeof( struct sockaddr_at );
1330 sat.sat_family = AF_APPLETALK;
1331 sat.sat_addr.s_net = iface->i_addr.sat_addr.s_net;
1332 sat.sat_addr.s_node = iface->i_addr.sat_addr.s_node;
1333 sat.sat_port = ap->ap_port;
1335 if ( bind( ap->ap_fd, (struct sockaddr *)&sat,
1336 sizeof( struct sockaddr_at )) < 0 ) {
1337 syslog( LOG_ERR, "bind %u.%u:%u: %m",
1338 ntohs( sat.sat_addr.s_net ),
1339 sat.sat_addr.s_node, sat.sat_port );
1341 /* remove all interfaces if we have a problem with bind */
1342 for (iface = interfaces; iface; iface = iface->i_next) {
1343 if (ifconfig( iface->i_name, SIOCDIFADDR, &iface->i_addr )) {
1344 #ifdef SIOCATALKDIFADDR
1345 #if (SIOCDIFADDR != SIOCATALKDIFADDR)
1346 ifconfig( iface->i_name, SIOCATALKDIFADDR, &iface->i_addr );
1356 /* recalculate nfds and fds */
1358 for ( nfds = 0, iface = interfaces; iface; iface = iface->i_next ) {
1359 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1360 FD_SET( ap->ap_fd, &fds );
1361 if ( ap->ap_fd > nfds ) {
1369 int ifconfig( iname, cmd, sa )
1372 struct sockaddr_at *sa;
1377 memset(&ifr, 0, sizeof(ifr));
1378 strcpy( ifr.ifr_name, iname );
1379 ifr.ifr_addr = *(struct sockaddr *)sa;
1381 if (( s = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1384 if ( ioctl( s, cmd, &ifr ) < 0 ) {
1389 if ( cmd == SIOCGIFADDR ) {
1390 *(struct sockaddr *)sa = ifr.ifr_addr;
1395 void dumpconfig( iface )
1396 struct interface *iface;
1400 printf( "%s", iface->i_name );
1401 if ( iface->i_flags & IFACE_RSEED ) {
1402 printf( " -router" );
1403 } else if ( iface->i_flags & IFACE_SEED ) {
1407 if ( iface->i_flags & IFACE_DONTROUTE)
1408 printf( " -dontroute");
1410 printf( " -phase" );
1411 if ( iface->i_flags & IFACE_PHASE1 ) {
1416 printf( " -net %d", ntohs( iface->i_rt->rt_firstnet ));
1417 if ( iface->i_rt->rt_lastnet != iface->i_rt->rt_firstnet ) {
1418 printf( "-%d", ntohs( iface->i_rt->rt_lastnet ));
1420 printf( " -addr %u.%u", ntohs( iface->i_addr.sat_addr.s_net ),
1421 iface->i_addr.sat_addr.s_node );
1422 printf( " -caddr %u.%u", ntohs( iface->i_caddr.sat_addr.s_net ),
1423 iface->i_caddr.sat_addr.s_node );
1424 for ( l = iface->i_rt->rt_zt; l; l = l->l_next ) {
1425 printf( " -zone %.*s", ((struct ziptab *)l->l_data)->zt_len,
1426 ((struct ziptab *)l->l_data)->zt_name );
1434 struct interface *iface;
1435 struct rtmptab *rtmp;
1439 for ( iface = interfaces; iface; iface = iface->i_next ) {
1440 for ( rtmp = iface->i_rt; rtmp; rtmp = rtmp->rt_inext ) {
1441 if ( rtmp->rt_gate == 0 ) {
1442 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
1443 printf( "%u-%u", ntohs( rtmp->rt_firstnet ),
1444 ntohs( rtmp->rt_lastnet ));
1446 printf( "%u", ntohs( rtmp->rt_firstnet ));
1449 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
1450 printf( "%u.%u for %u-%u",
1451 ntohs( rtmp->rt_gate->g_sat.sat_addr.s_net ),
1452 rtmp->rt_gate->g_sat.sat_addr.s_node,
1453 ntohs( rtmp->rt_firstnet ),
1454 ntohs( rtmp->rt_lastnet ));
1456 printf( "%u.%u for %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 ));
1463 if ( rtmp->rt_iprev == 0 && rtmp != iface->i_rt ) {
1467 for ( l = rtmp->rt_zt; l; l = l->l_next ) {
1468 zt = (struct ziptab *)l->l_data;
1469 printf( " %.*s", zt->zt_len, zt->zt_name );
1482 struct interface *iface;
1483 struct rtmptab *rtmp;
1487 for ( zt = ziptab; zt; zt = zt->zt_next ) {
1488 printf( "%.*s", zt->zt_len, zt->zt_name );
1489 for ( l = zt->zt_rt; l; l = l->l_next ) {
1490 rtmp = (struct rtmptab *)l->l_data;
1491 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
1492 printf( " %u-%u", ntohs( rtmp->rt_firstnet ),
1493 ntohs( rtmp->rt_lastnet ));
1495 printf( " %u", ntohs( rtmp->rt_firstnet ));
1497 if ( rtmp->rt_iprev == 0 && rtmp->rt_gate != 0 ) {