2 * $Id: main.c,v 1.12 2002-01-04 04:45:47 sibaz 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 */
38 #include <net/route.h>
41 #include <net/route.h>
44 #include <atalk/logger.h>
52 #include <netatalk/endian.h>
53 #include <netatalk/at.h>
54 #include <atalk/compat.h>
55 #include <atalk/zip.h>
56 #include <atalk/rtmp.h>
57 #include <atalk/ddp.h>
58 #include <atalk/atp.h>
59 #include <atalk/paths.h>
60 #include <atalk/util.h>
63 #include <sys/sockio.h>
67 #include "interface.h"
75 /* Forward Declarations */
76 int ifconfig(const char *iname, unsigned long cmd, struct sockaddr_at *sa);
78 /* FIXME/SOCKLEN_T: socklen_t is a unix98 feature */
80 #define SOCKLEN_T unsigned int
81 #endif /* SOCKLEN_T */
84 #define WEXITSTATUS(x) ((x).w_retcode)
85 #endif /* WEXITSTATUS */
87 /* linux has a special ioctl for appletalk device destruction. as of
88 * 2.1.57, SIOCDIFADDR works w/ linux. okay, we need to deal with the
89 * fact that SIOCDIFADDR may be defined on linux despite the fact that
91 #if !defined(SIOCDIFADDR) && defined(SIOCATALKDIFADDR)
92 #define SIOCDIFADDR SIOCATALKDIFADDR
95 #define elements(a) (sizeof(a)/sizeof((a)[0]))
99 extern int rtmp_packet();
100 extern int nbp_packet();
101 extern int aep_packet();
102 extern int zip_packet();
106 struct atserv atserv[] = {
107 { "rtmp", 1, rtmp_packet }, /* 0 */
108 { "nbp", 2, nbp_packet }, /* 1 */
109 { "echo", 4, aep_packet }, /* 2 */
110 { "zip", 6, zip_packet }, /* 3 */
112 int atservNATSERV = elements( atserv );
114 struct interface *interfaces = NULL, *ciface = NULL;
116 int debug = 0, quiet = 0, chatty = 0;
117 char *configfile = NULL;
118 int ziptimeout = 0, transition = 0;
119 int stabletimer, stable = 0, newrtmpdata = 0, noparent = 0;
120 static int ninterfaces;
121 int defphase = IFACE_PHASE2;
124 char Packet[ PKTSZ ];
125 char *version = VERSION;
126 static char *pidfile = _PATH_ATALKDLOCK;
131 int readconf( char * );
132 int getifconf( void );
133 int writeconf( char * );
135 /* this is the messiest of the bunch as atalkd can exit pretty much
136 * everywhere. we delete interfaces here instead of in as_down. */
137 static void atalkd_exit(const int i)
140 struct interface *iface;
142 for (iface = interfaces; iface; iface = iface->i_next) {
143 if (ifconfig( iface->i_name, SIOCDIFADDR, &iface->i_addr)) {
144 #ifdef SIOCATALKDIFADDR
145 #if (SIOCDIFADDR != SIOCATALKDIFADDR)
146 if (!ifconfig(iface->i_name, SIOCATALKDIFADDR, &iface->i_addr))
148 #endif /* SIOCDIFADDR != SIOCATALKDIFADDR */
149 #endif /* SIOCATALKIFADDR */
150 LOG(log_error, logtype_default, "difaddr(%u.%u): %s",
151 ntohs(iface->i_addr.sat_addr.s_net),
152 iface->i_addr.sat_addr.s_node, strerror(errno));
155 #endif /* SOPCDOFADDR */
157 server_unlock(pidfile);
162 #if !defined( ibm032 ) && !defined( _IBMR2 )
164 #endif /* ibm032 _IBMR2 */
167 struct sockaddr_at sat;
170 struct rtmp_tuple rt;
171 struct atport *ap, *zap, *rap;
172 struct interface *iface, *iface2;
173 struct gate *gate, *fgate = NULL;
174 struct rtmptab *rtmp, *frtmp;
176 char *data, *end, packet[ ATP_BUFSIZ ];
180 memset(&sat, 0, sizeof( struct sockaddr_at ));
181 for ( iface = interfaces; iface; iface = iface->i_next ) {
182 if ( iface->i_flags & IFACE_LOOPBACK ) {
185 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
186 if ( ap->ap_packet == zip_packet ) {
189 if ( ap->ap_packet == rtmp_packet ) {
194 if (( iface->i_flags & ( IFACE_ADDR|IFACE_CONFIG|IFACE_NOROUTER )) ==
196 if ( iface->i_time < 3 ) {
197 if ( iface->i_flags & IFACE_PHASE1 ) {
198 if (rtmp_request( iface ) < 0) {
199 LOG(log_error, logtype_default, "rtmp_request: %s", strerror(errno));
204 if (zip_getnetinfo( iface ) < 0) {
205 LOG(log_error, logtype_default, "zip_getnetinfo: %s", strerror(errno));
212 iface->i_flags |= IFACE_NOROUTER;
213 if ((iface->i_flags & IFACE_ISROUTER)) {
214 if (( iface->i_flags & IFACE_SEED ) == 0 ) {
216 * No seed info, and we've got multiple interfaces.
219 LOG(log_info, logtype_default,
220 "as_timer multiple interfaces, no seed" );
221 LOG(log_info, logtype_default, "as_timer can't configure %s",
223 LOG(log_info, logtype_default, "as_timer waiting for router" );
228 * Complete configuration for iface, and boot next
231 iface->i_flags |= IFACE_CONFIG;
232 for ( zt = iface->i_czt; zt; zt = zt->zt_next ) {
233 if (addzone( iface->i_rt, zt->zt_len,
235 LOG(log_error, logtype_default, "addzone: %s", strerror(errno));
239 if ( iface->i_rt->rt_zt ) {
240 iface->i_rt->rt_flags &= ~RTMPTAB_ZIPQUERY;
241 iface->i_rt->rt_flags |= RTMPTAB_HASZONES;
243 if ( iface->i_flags & IFACE_PHASE1 ) {
244 LOG(log_info, logtype_default,
245 "as_timer configured %s phase 1 from seed",
247 setaddr( iface, IFACE_PHASE1,
248 iface->i_caddr.sat_addr.s_net,
249 iface->i_addr.sat_addr.s_node,
250 iface->i_caddr.sat_addr.s_net,
251 iface->i_caddr.sat_addr.s_net );
253 LOG(log_info, logtype_default,
254 "as_timer configured %s phase 2 from seed",
258 if ( looproute( iface, RTMP_ADD )) { /* -1 or 1 */
259 LOG(log_error, logtype_default,
260 "as_timer: can't route %u.%u to loop: %s",
261 ntohs( iface->i_addr.sat_addr.s_net ),
262 iface->i_addr.sat_addr.s_node,
266 if ( iface == ciface ) {
267 ciface = ciface->i_next;
273 * Configure for no router operation. Wait for a route
274 * to become available in rtmp_packet().
276 LOG(log_info, logtype_default, "config for no router" );
278 if ( iface->i_flags & IFACE_PHASE2 ) {
279 iface->i_rt->rt_firstnet = 0;
280 iface->i_rt->rt_lastnet = htons( STARTUP_LASTNET );
281 setaddr( iface, IFACE_PHASE2,
282 iface->i_addr.sat_addr.s_net,
283 iface->i_addr.sat_addr.s_node,
284 0, htons( STARTUP_LASTNET ));
286 if ( looproute( iface, RTMP_ADD ) ) { /* -1 or 1 */
287 LOG(log_error, logtype_default,
288 "as_timer: can't route %u.%u to loopback: %s",
289 ntohs( iface->i_addr.sat_addr.s_net ),
290 iface->i_addr.sat_addr.s_node,
295 if ( iface == ciface ) {
296 ciface = ciface->i_next;
303 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
305 free( (caddr_t)fgate );
310 data = packet + 1 + sizeof( struct ziphdr );
311 end = packet + sizeof( packet );
314 sat.sat_port = zap->ap_port;
317 * Perform timeouts on routers. If we've only got one
318 * interface, we'll use these timeouts to decide that
319 * our zone has gone away.
321 if ( ++gate->g_state >= RTMPTAB_BAD ) {
322 LOG(log_info, logtype_default, "as_timer gateway %u.%u down",
323 ntohs( gate->g_sat.sat_addr.s_net ),
324 gate->g_sat.sat_addr.s_node );
327 frtmp = rtmp->rt_next;
328 if ( rtmp->rt_hops == RTMPHOPS_POISON ||
329 rtmp->rt_iprev == 0 ) {
332 rtmp->rt_hops = RTMPHOPS_POISON;
333 if ((cc = rtmp_replace( rtmp )) < 0) {
334 LOG(log_error, logtype_default, "rtmp_replace: %s", strerror(errno));
338 gate->g_state = rtmp->rt_state = RTMPTAB_GOOD;
343 if ( gate->g_rt == 0 ) {
344 if ( gate->g_prev == 0 ) {
345 gate->g_iface->i_gate = gate->g_next;
347 gate->g_prev->g_next = gate->g_next;
349 if ( gate->g_next != 0 ) {
350 gate->g_next->g_prev = gate->g_prev;
352 fgate = gate; /* can't free here, just mark it */
355 * If this is the last router on the only interface,
356 * reconfigure our netrange. By marking the interface
357 * as having no router, we will notice when a router
360 * XXX: actually, we always reconfigure an interface
361 * if we're not a seed router.
364 if ( gate->g_iface->i_gate == 0 &&
365 ((iface->i_flags & IFACE_SEED) == 0)) {
366 gate->g_iface->i_flags |= IFACE_NOROUTER;
367 gate->g_iface->i_flags &= ~IFACE_CONFIG;
369 /* get rid of any zones associated with this iface */
370 if (gate->g_iface->i_rt->rt_zt) {
371 rtmp_delzonemap(gate->g_iface->i_rt);
372 gate->g_iface->i_rt->rt_flags &= ~RTMPTAB_HASZONES;
375 LOG(log_info, logtype_default, "as_timer last gateway down" );
377 /* Set netrange to 0-fffe. */
378 if ( gate->g_iface->i_flags & IFACE_PHASE2 ) {
379 gate->g_iface->i_rt->rt_firstnet = 0;
380 gate->g_iface->i_rt->rt_lastnet =
381 htons( STARTUP_LASTNET );
382 setaddr( iface, IFACE_PHASE2,
383 iface->i_addr.sat_addr.s_net,
384 iface->i_addr.sat_addr.s_node,
385 0, htons( STARTUP_LASTNET ));
392 * If we don't have a zone for our interface yet, ask for
393 * it from any router (all routers) on the interface.
395 if (( iface->i_rt->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
396 iface->i_rt->rt_flags |= RTMPTAB_ZIPQUERY;
397 memcpy( data, &iface->i_rt->rt_firstnet, sizeof( u_short ));
398 data += sizeof( u_short );
405 * Delete old routing tuples.
407 if ( rtmp->rt_state != RTMPTAB_PERM ) {
412 * We've not been updated for this route in a while. If
413 * it's not in use, go ahead and remove it. If it is in
414 * use, mark the route as down (POISON), and look for a
415 * better route. If one is found, delete this route and use
416 * the new one. If it's not found, mark the route as GOOD
417 * (so we'll propogate our poison) and delete it the next
418 * time it becomes BAD.
420 if ( rtmp->rt_state >= RTMPTAB_BAD ) {
421 frtmp = rtmp->rt_next;
422 if ( rtmp->rt_iprev == 0 ) { /* not in use */
424 } else { /* in use */
425 if ( rtmp->rt_hops == RTMPHOPS_POISON ) {
428 rtmp->rt_hops = RTMPHOPS_POISON;
429 if ((cc = rtmp_replace( rtmp )) < 0) {
430 LOG(log_error, logtype_default, "rtmp_replace: %s", strerror(errno));
434 rtmp->rt_state = RTMPTAB_GOOD;
444 if ( rtmp->rt_iprev &&
445 ( rtmp->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
446 if ( data + sizeof( u_short ) > end || n == 255 ) {
447 /* send what we've got */
448 zh.zh_op = ZIPOP_QUERY;
452 *data++ = DDPTYPE_ZIP;
453 memcpy( data, &zh, sizeof( struct ziphdr ));
455 if ( sendto( zap->ap_fd, packet, cc, 0,
456 (struct sockaddr *)&sat,
457 sizeof( struct sockaddr_at )) < 0 ) {
458 LOG(log_error, logtype_default, "as_timer sendto: %s", strerror(errno) );
463 data = packet + 1 + sizeof( struct ziphdr );
464 end = packet + sizeof( packet );
468 * rt_nzq is number of ZIP Queries we've issued for a
469 * given netrange. If we've got ziptimeout on, we
470 * will only ask 3 times for any given netrange.
471 * Interestingly enough, since rt_nzq is a u_char,
472 * it will overflow after a while. This means we will
473 * periodically ask for nets that we've decided not to
474 * ask about, and warn that we can't get it's zone.
476 if ( rtmp->rt_nzq++ == 3 ) {
477 LOG(log_info, logtype_default, "as_timer can't get zone for %u",
478 ntohs( rtmp->rt_firstnet ));
480 if ( rtmp->rt_nzq > 3 ) {
482 rtmp = rtmp->rt_next;
488 rtmp->rt_flags |= RTMPTAB_ZIPQUERY;
489 memcpy( data, &rtmp->rt_firstnet, sizeof( u_short ));
490 data += sizeof( u_short );
493 rtmp = rtmp->rt_next;
496 /* send what we've got */
498 zh.zh_op = ZIPOP_QUERY;
502 *data++ = DDPTYPE_ZIP;
503 memcpy( data, &zh, sizeof( struct ziphdr ));
505 if ( sendto( zap->ap_fd, packet, cc, 0, (struct sockaddr *)&sat,
506 sizeof( struct sockaddr_at )) < 0 ) {
507 LOG(log_error, logtype_default, "as_timer sendto: %s", strerror(errno) );
512 free( (caddr_t)fgate );
517 * Send RTMP broadcasts if we have multiple interfaces or our
518 * interface is configured as a router.
520 if ((iface->i_flags & IFACE_ISROUTER)) {
522 sat.sat_len = sizeof( struct sockaddr_at );
524 sat.sat_family = AF_APPLETALK;
525 sat.sat_addr.s_net = ATADDR_ANYNET;
526 sat.sat_addr.s_node = ATADDR_BCAST;
527 sat.sat_port = rap->ap_port;
530 end = data + sizeof( packet );
531 *data++ = DDPTYPE_RTMPRD;
532 rh.rh_net = iface->i_addr.sat_addr.s_net;
534 rh.rh_node = iface->i_addr.sat_addr.s_node;
535 memcpy( data, &rh, sizeof( struct rtmp_head ));
536 data += sizeof( struct rtmp_head );
540 if ( iface->i_flags & IFACE_PHASE1 ) {
543 memcpy( data, &rt, SZ_RTMPTUPLE );
544 data += SZ_RTMPTUPLE;
546 rt.rt_net = iface->i_rt->rt_firstnet;
548 memcpy( data, &rt, SZ_RTMPTUPLE );
549 data += SZ_RTMPTUPLE;
551 rt.rt_net = iface->i_rt->rt_lastnet;
553 memcpy( data, &rt, SZ_RTMPTUPLE );
554 data += SZ_RTMPTUPLE;
557 for ( iface2 = interfaces; iface2; iface2 = iface2->i_next ) {
559 /* XXX: there used to be a bit checking against iface ==
560 iface2. also, we don't want to send an rtmp broadcast
561 to an interface that doesn't want it. */
562 if ((( iface2->i_flags & IFACE_CONFIG ) == 0) ||
563 ((iface2->i_flags & IFACE_ISROUTER) == 0)) {
567 * Fill in tuples. Always send the same thing, regardless
568 * of the phase of the destination. Routers who don't
569 * understand extended rtmp packets will toss extended
570 * tuples because their distance will have the high bit set.
572 for ( rtmp = iface2->i_rt; rtmp; rtmp = rtmp->rt_inext ) {
573 /* don't broadcast routes we have no zone for */
574 if ( rtmp->rt_zt == 0 ||
575 ( rtmp->rt_flags & RTMPTAB_ZIPQUERY ) ||
576 ( rtmp->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
580 if ((( rtmp->rt_flags & RTMPTAB_EXTENDED ) &&
581 data + 2 * SZ_RTMPTUPLE > end ) ||
582 data + SZ_RTMPTUPLE > end ) {
583 if ( sendto( rap->ap_fd, packet, data - packet, 0,
584 (struct sockaddr *)&sat,
585 sizeof( struct sockaddr_at )) < 0 ) {
586 LOG(log_error, logtype_default, "as_timer sendto %u.%u (%u): %s",
587 ntohs( sat.sat_addr.s_net ),
589 ntohs( iface->i_rt->rt_firstnet ),
593 if ( iface->i_flags & IFACE_PHASE2 ) {
594 data = packet + 1 + sizeof( struct rtmp_head ) +
597 data = packet + 1 + sizeof( struct rtmp_head ) +
603 rt.rt_net = rtmp->rt_firstnet;
604 rt.rt_dist = rtmp->rt_hops;
605 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
608 memcpy( data, &rt, SZ_RTMPTUPLE );
609 data += SZ_RTMPTUPLE;
611 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
612 rt.rt_net = rtmp->rt_lastnet;
614 memcpy( data, &rt, SZ_RTMPTUPLE );
615 data += SZ_RTMPTUPLE;
623 if ( sendto( rap->ap_fd, packet, data - packet, 0,
624 (struct sockaddr *)&sat,
625 sizeof( struct sockaddr_at )) < 0 ) {
626 LOG(log_error, logtype_default, "as_timer sendto %u.%u (%u): %s",
627 ntohs( sat.sat_addr.s_net ),
629 ntohs( iface->i_rt->rt_firstnet ),
637 * Check if we're stable. Each time we configure an interface, we
638 * sent stabletimer to UNSTABLE. If stabletimer ever gets to
639 * STABLEANYWAY, we give up and decide to "be" stable anyway.
640 * Normally, we wait for stabletimer get <= STABLE with no new rtmp
641 * data and all zip data complete.
644 if ( stabletimer <= STABLE && !newrtmpdata && !sentzipq ) {
645 /* write out config file */
647 writeconf( configfile );
649 if ( stabletimer-- <= STABLEANYWAY ) {
655 if ( stable && !noparent ) {
657 LOG(log_info, logtype_default, "ready %d/%d/%d", stabletimer, newrtmpdata,
661 * Seems like we could get here more than once...
663 if ( kill( getpid(), SIGSTOP ) < 0 ) {
664 LOG(log_error, logtype_default, "as_timer: kill-self failed!" );
678 * Consistency check...
682 struct rtmptab *rtmp;
683 struct list *lr, *lz;
686 for ( zt = ziptab; zt; zt = zt->zt_next ) {
687 for ( lr = zt->zt_rt; lr; lr = lr->l_next ) {
688 rtmp = (struct rtmptab *)lr->l_data;
689 if ( rtmp->rt_iprev == 0 && rtmp->rt_gate != 0 ) {
690 LOG(log_error, logtype_default, "%.*s has %u-%u (unused)\n",
691 zt->zt_len, zt->zt_name, ntohs( rtmp->rt_firstnet ),
692 ntohs( rtmp->rt_lastnet ));
695 for ( lz = rtmp->rt_zt; lz; lz = lz->l_next ) {
696 if ( zt == (struct ziptab *)lz->l_data ) {
701 LOG(log_error, logtype_default, "no map from %u-%u to %.*s\n",
702 ntohs( rtmp->rt_firstnet ),
703 ntohs( rtmp->rt_lastnet ),
704 zt->zt_len, zt->zt_name );
712 #if !defined( ibm032 ) && !defined( _IBMR2 )
714 #endif /* ! ibm032 && ! _IBMR2 */
717 struct interface *iface;
724 if (( rtmpdebug = fopen( _PATH_ATALKDEBUG, "w" )) == NULL ) {
725 LOG(log_error, logtype_default, "rtmp: %s", strerror(errno) );
728 for ( iface = interfaces; iface; iface = iface->i_next ) {
729 fprintf( rtmpdebug, "interface %s %u.%u ", iface->i_name,
730 ntohs( iface->i_addr.sat_addr.s_net ),
731 iface->i_addr.sat_addr.s_node );
732 if ( iface->i_flags & IFACE_PHASE1 ) {
733 putc( '1', rtmpdebug );
735 if ( iface->i_flags & IFACE_PHASE2 ) {
736 putc( '2', rtmpdebug );
738 if ( iface->i_flags & IFACE_RSEED ) {
739 putc( 'R', rtmpdebug );
741 if ( iface->i_flags & IFACE_SEED ) {
742 putc( 'S', rtmpdebug );
744 if ( iface->i_flags & IFACE_DONTROUTE ) {
745 putc( 'D', rtmpdebug );
747 if ( iface->i_flags & IFACE_ADDR ) {
748 putc( 'A', rtmpdebug );
750 if ( iface->i_flags & IFACE_CONFIG ) {
751 putc( 'C', rtmpdebug );
753 if ( iface->i_flags & IFACE_NOROUTER ) {
754 putc( 'N', rtmpdebug );
756 if ( iface->i_flags & IFACE_LOOP ) {
757 putc( 'L', rtmpdebug );
759 putc( '\n', rtmpdebug );
762 fprintf( rtmpdebug, "\t%u-%u ",
763 ntohs( iface->i_rt->rt_firstnet ),
764 ntohs( iface->i_rt->rt_lastnet ));
765 if ( iface->i_rt->rt_flags & RTMPTAB_ZIPQUERY ) {
766 putc( 'q', rtmpdebug );
768 if ( iface->i_rt->rt_flags & RTMPTAB_HASZONES ) {
769 putc( 'z', rtmpdebug );
771 if ( iface->i_rt->rt_flags & RTMPTAB_EXTENDED ) {
772 putc( 'x', rtmpdebug );
774 putc( 'i', rtmpdebug );
775 for ( l = iface->i_rt->rt_zt; l; l = l->l_next ) {
776 zt = (struct ziptab *)l->l_data;
777 fprintf( rtmpdebug, " '%.*s'", zt->zt_len, zt->zt_name );
779 fprintf( rtmpdebug, "\n" );
782 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
783 fprintf( rtmpdebug, "gate %u.%u %X\n",
784 ntohs( gate->g_sat.sat_addr.s_net ),
785 gate->g_sat.sat_addr.s_node, gate->g_state );
786 for ( rt = gate->g_rt; rt; rt = rt->rt_next ) {
787 fprintf( rtmpdebug, "\t%u-%u ", ntohs( rt->rt_firstnet ),
788 ntohs( rt->rt_lastnet ));
789 if ( rt->rt_flags & RTMPTAB_ZIPQUERY ) {
790 putc( 'q', rtmpdebug );
792 if ( rt->rt_flags & RTMPTAB_HASZONES ) {
793 putc( 'z', rtmpdebug );
795 if ( rt->rt_flags & RTMPTAB_EXTENDED ) {
796 putc( 'x', rtmpdebug );
798 if ( rt->rt_iprev ) {
799 putc( 'i', rtmpdebug );
801 for ( l = rt->rt_zt; l; l = l->l_next ) {
802 zt = (struct ziptab *)l->l_data;
803 fprintf( rtmpdebug, " '%.*s'", zt->zt_len, zt->zt_name );
805 fprintf( rtmpdebug, "\n" );
814 * Called when SIGTERM is recieved. Remove all routes and then exit.
816 #if !defined( ibm032 ) && !defined( _IBMR2 )
818 #endif /* ! ibm032 && ! _IBMR2 */
821 struct interface *iface;
825 for ( iface = interfaces; iface; iface = iface->i_next ) {
826 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
827 for ( rt = gate->g_rt; rt; rt = rt->rt_next ) {
828 if ( rt->rt_iprev ) {
829 if ( gateroute( RTMP_DEL, rt ) < 0 ) {
830 LOG(log_error, logtype_default, "as_down remove %u-%u failed: %s",
831 ntohs( rt->rt_firstnet ),
832 ntohs( rt->rt_lastnet ),
838 if ( iface->i_flags & IFACE_LOOP ) {
839 if (looproute( iface, RTMP_DEL )) {
840 LOG(log_error, logtype_default, "as_down remove %s %u.%u failed: %s",
841 iface->i_name, ntohs( iface->i_addr.sat_addr.s_net ),
842 iface->i_addr.sat_addr.s_node,
848 LOG(log_info, logtype_default, "done" );
859 struct sockaddr_at sat;
862 struct interface *iface;
871 while (( c = getopt( ac, av, "12qsdtf:P:v" )) != EOF ) {
874 defphase = IFACE_PHASE1;
878 defphase = IFACE_PHASE2;
889 case 'q' : /* don't seed */
893 case 's' : /* seed */
897 case 't' : /* transition */
901 case 'P' : /* pid file */
905 case 'v' : /* version */
906 printf( "atalkd (version %s)\n", version );
911 fprintf( stderr, "Unknown option -- '%c'\n", c );
915 if ( optind != ac ) {
916 fprintf( stderr, "Too many arguments.\n" );
920 if (( prog = strrchr( av[ 0 ], '/' )) == NULL ) {
927 * Configure loop back address first, so appearances of "lo0" in
928 * the config file fail. Also insures that lo0 gets configured,
929 * even if there's some hangup during configuration of some
932 if (( interfaces = newiface( LOOPIFACE )) == NULL ) {
933 perror( "newiface" );
936 interfaces->i_flags |= IFACE_PHASE2 | IFACE_LOOPBACK;
939 * Check our initial configuration before we fork. This way we can
940 * complain about syntax errors on stdout.
942 * Basically, if we're going to read our config file, we should read
943 * it and initialize our data structures. If we're not going to read
944 * our config file, use GIFCONF to initialize our data structures.
946 if ( readconf( configfile ) < 0 && getifconf() < 0 ) {
947 fprintf( stderr, "%s: can't get interfaces, exiting.\n", prog );
951 /* we need to count up our interfaces so that we can simplify things
952 * later. we also need to figure out if we have more than one interface
953 * that is routing. */
954 for (i = 0, ninterfaces = 0, iface = interfaces; iface;
955 iface=iface->i_next) {
956 if (iface->i_flags & IFACE_DONTROUTE)
960 i = ninterfaces - i; /* number of routable interfaces */
963 * At this point, we have (at least partially) initialized data
964 * structures. Fill in what we can and verify that nothing is obviously
967 for (iface = interfaces; iface; iface = iface->i_next) {
968 /* Apply the default phase */
969 if (( iface->i_flags & IFACE_PHASE1 ) == 0 &&
970 ( iface->i_flags & IFACE_PHASE2 ) == 0 ) {
971 iface->i_flags |= defphase;
974 /* set up router flag information. if we have multiple interfaces
975 * and DONTROUTE isn't set, set up ROUTER. i is the number of
976 * interfaces that don't have the DONTROUTE flag set. */
977 if ((i > IFBASE) && ((iface->i_flags & IFACE_DONTROUTE) == 0)) {
978 iface->i_flags |= IFACE_ISROUTER;
981 /* Set default addresses */
982 if ( iface->i_rt == NULL ) {
983 if (( iface->i_rt = newrt(iface)) == NULL ) {
988 if ( iface->i_flags & IFACE_PHASE1 ) {
989 iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet =
990 iface->i_caddr.sat_addr.s_net;
992 if ( iface->i_caddr.sat_addr.s_net != ATADDR_ANYNET ||
993 ( iface->i_flags & IFACE_LOOPBACK )) {
994 iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet =
995 iface->i_caddr.sat_addr.s_net;
997 iface->i_rt->rt_firstnet = htons( STARTUP_FIRSTNET );
998 iface->i_rt->rt_lastnet = htons( STARTUP_LASTNET );
1003 if (( iface->i_flags & IFACE_PHASE1 ) == 0 ) {
1004 iface->i_rt->rt_flags |= RTMPTAB_EXTENDED;
1007 if ( iface->i_caddr.sat_addr.s_net == ATADDR_ANYNET ) {
1008 iface->i_caddr.sat_addr.s_net = iface->i_rt->rt_firstnet;
1012 dumpconfig( iface ); /* probably needs args */
1017 * A little consistency check...
1019 if ( ninterfaces < IFBASE ) {
1020 fprintf( stderr, "%s: zero interfaces, exiting.\n", prog );
1024 /* do this here so that we can use ifconfig */
1026 if ( plumb() < 0 ) {
1027 fprintf(stderr, "can't establish STREAMS plumbing, exiting.\n" );
1030 #endif /* __svr4__ */
1032 /* delete pre-existing interface addresses. */
1034 for (iface = interfaces; iface; iface = iface->i_next) {
1035 if (ifconfig(iface->i_name, SIOCDIFADDR, &iface->i_addr)) {
1036 #ifdef SIOCATALKDIFADDR
1037 #if (SIOCDIFADDR != SIOCATALKDIFADDR)
1038 ifconfig(iface->i_name, SIOCATALKDIFADDR, &iface->i_addr);
1039 #endif /* SIOCDIFADDR != SIOCATALKDIFADDR */
1040 #endif /* SIOCATALKDIFADDR */
1043 #endif /* SIOCDIFADDR */
1046 * Disassociate. The child will send itself a signal when it is
1047 * stable. This indicates that other processes may begin using
1050 switch (i = server_lock("atalkd", pidfile, debug)) {
1055 default: /* parent */
1057 * Wait for the child to send itself a SIGSTOP, after which
1058 * we send it a SIGCONT and exit ourself.
1060 if ( wait3( &status, WUNTRACED, (struct rusage *)0 ) != i) {
1061 perror( "wait3" ); /* Child died? */
1064 if ( !WIFSTOPPED( status )) {
1065 fprintf( stderr, "AppleTalk not up! Check your syslog for the reason." );
1066 if ( WIFEXITED( status )) {
1067 fprintf( stderr, " Child exited with %d.\n",
1068 WEXITSTATUS( status ));
1070 fprintf( stderr, " Child died.\n" );
1074 if ( kill(i, SIGCONT ) < 0 ) {
1082 openlog( prog, LOG_PID );
1084 set_processname(prog);
1085 syslog_setup(log_debug, logtype_default, logoption_pid, logfacility_daemon );
1088 LOG(log_info, logtype_default, "restart (%s)", version );
1091 * Socket for use in routing ioctl()s. Can't add routes to our
1092 * interfaces until we have our routing socket.
1095 if (( rtfd = socket( PF_ROUTE, SOCK_RAW, AF_APPLETALK )) < 0 ) {
1096 LOG(log_error, logtype_default, "route socket: %s", strerror(errno) );
1099 if ( shutdown( rtfd, 0 ) < 0 ) {
1100 LOG(log_error, logtype_default, "route shutdown: %s", strerror(errno) );
1104 if (( rtfd = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1105 LOG(log_error, logtype_default, "route socket: %s", strerror(errno) );
1110 memset(&sv, 0, sizeof(sv));
1111 sv.sa_handler = as_down;
1112 sigemptyset( &sv.sa_mask );
1113 sigaddset( &sv.sa_mask, SIGUSR1 );
1114 sigaddset( &sv.sa_mask, SIGALRM );
1115 sigaddset( &sv.sa_mask, SIGTERM );
1116 sv.sa_flags = SA_RESTART;
1117 if ( sigaction( SIGTERM, &sv, NULL) < 0 ) {
1118 LOG(log_error, logtype_default, "sigterm: %s", strerror(errno) );
1122 sv.sa_handler = as_debug;
1123 sigemptyset( &sv.sa_mask );
1124 sigaddset( &sv.sa_mask, SIGUSR1 );
1125 sigaddset( &sv.sa_mask, SIGALRM );
1126 sigaddset( &sv.sa_mask, SIGTERM );
1127 sv.sa_flags = SA_RESTART;
1128 if ( sigaction( SIGUSR1, &sv, NULL) < 0 ) {
1129 LOG(log_error, logtype_default, "sigusr1: %s", strerror(errno) );
1133 sv.sa_handler = as_timer;
1134 sigemptyset( &sv.sa_mask );
1135 sigaddset( &sv.sa_mask, SIGUSR1 );
1136 sigaddset( &sv.sa_mask, SIGALRM );
1137 sigaddset( &sv.sa_mask, SIGTERM );
1138 sv.sa_flags = SA_RESTART;
1139 if ( sigaction( SIGALRM, &sv, NULL) < 0 ) {
1140 LOG(log_error, logtype_default, "sigalrm: %s", strerror(errno) );
1144 it.it_interval.tv_sec = 10L;
1145 it.it_interval.tv_usec = 0L;
1146 it.it_value.tv_sec = 10L;
1147 it.it_value.tv_usec = 0L;
1148 if ( setitimer( ITIMER_REAL, &it, NULL) < 0 ) {
1149 LOG(log_error, logtype_default, "setitimer: %s", strerror(errno) );
1153 ciface = interfaces;
1157 if ( select( nfds, &readfds, NULL, NULL, NULL) < 0 ) {
1158 if ( errno == EINTR ) {
1162 LOG(log_error, logtype_default, "select: %s", strerror(errno) );
1167 for ( iface = interfaces; iface; iface = iface->i_next ) {
1168 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1169 if ( FD_ISSET( ap->ap_fd, &readfds )) {
1170 if ( ap->ap_packet ) {
1171 fromlen = sizeof( struct sockaddr_at );
1172 if (( c = recvfrom( ap->ap_fd, Packet, sizeof( Packet ),
1173 0, (struct sockaddr *)&sat, &fromlen )) < 0 ) {
1174 LOG(log_error, logtype_default, "recvfrom: %s", strerror(errno) );
1179 printf( "packet from %u.%u on %s (%x) %d (%d)\n",
1180 ntohs( sat.sat_addr.s_net ),
1181 sat.sat_addr.s_node, iface->i_name,
1182 iface->i_flags, ap->ap_port, ap->ap_fd );
1183 bprint( Packet, c );
1187 if ( sighold( SIGALRM ) || sighold( SIGUSR1 )) {
1188 LOG(log_error, logtype_default, "sighold: %s", strerror(errno) );
1191 #else /* __svr4__ */
1192 mask = sigsetmask( sigmask( SIGALRM ) |
1193 sigmask( SIGUSR1 ));
1194 #endif /* __svr4__ */
1195 if (( *ap->ap_packet )( ap, &sat, Packet, c ) < 0) {
1196 LOG(log_error, logtype_default, "ap->ap_packet: %s", strerror(errno));
1204 if ( sigrelse( SIGUSR1 ) || sigrelse( SIGALRM )) {
1205 LOG(log_error, logtype_default, "sigrelse: %s", strerror(errno) );
1208 #else /* __svr4__ */
1210 #endif /* __svr4__ */
1219 * This code is called (from main(), as_timer(), zip_packet(),
1220 * and rtmp_packet()) to set the initial "bootstrapping" address
1223 void bootaddr( iface )
1224 struct interface *iface;
1231 if ( iface->i_flags & IFACE_ADDR ) {
1232 LOG(log_error, logtype_default, "bootaddr OOPS!" );
1236 if ( iface->i_flags & IFACE_PHASE1 ) {
1237 setaddr( iface, IFACE_PHASE1, 0,
1238 iface->i_caddr.sat_addr.s_node, 0, 0 );
1240 if ( iface->i_flags & IFACE_LOOPBACK ) {
1241 iface->i_flags |= IFACE_CONFIG | IFACE_ADDR;
1242 if ( ciface == iface ) {
1243 ciface = ciface->i_next;
1247 } else if (rtmp_request( iface ) < 0) {
1248 LOG(log_error, logtype_default, "bootaddr (rtmp_request): %s", strerror(errno));
1253 setaddr( iface, IFACE_PHASE2, iface->i_caddr.sat_addr.s_net,
1254 iface->i_caddr.sat_addr.s_node,
1255 iface->i_rt->rt_firstnet, iface->i_rt->rt_lastnet );
1257 if ( iface->i_flags & IFACE_LOOPBACK ) {
1258 iface->i_flags |= IFACE_CONFIG | IFACE_ADDR;
1259 if ( ciface == iface ) {
1260 ciface = ciface->i_next;
1264 } else if (zip_getnetinfo( iface ) < 0) {
1265 LOG(log_error, logtype_default, "bootaddr (zip_getnetinfo): %s", strerror(errno));
1270 iface->i_flags |= IFACE_ADDR;
1271 stabletimer = UNSTABLE;
1277 * to manage the i_ports field and the fds for select().
1279 void setaddr(struct interface *iface,
1280 u_int8_t phase, u_int16_t net, u_int8_t node,
1281 u_int16_t first, u_int16_t last)
1287 struct sockaddr_at sat;
1290 if ( iface->i_ports == NULL ) { /* allocate port structures */
1291 for ( i = 0, as = atserv; i < atservNATSERV; i++, as++ ) {
1292 if (( se = getservbyname( as->as_name, "ddp" )) == NULL ) {
1293 LOG(log_info, logtype_default, "%s: service unknown", as->as_name );
1295 as->as_port = ntohs( se->s_port );
1297 if (( ap = (struct atport *)malloc( sizeof( struct atport ))) ==
1299 LOG(log_error, logtype_default, "malloc: %s", strerror(errno) );
1303 ap->ap_next = iface->i_ports;
1304 ap->ap_iface = iface;
1305 ap->ap_port = as->as_port;
1306 ap->ap_packet = as->as_packet;
1308 iface->i_ports = ap;
1310 } else { /* close ports */
1311 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1312 (void)close( ap->ap_fd );
1317 iface->i_addr.sat_len = sizeof( struct sockaddr_at );
1319 iface->i_addr.sat_family = AF_APPLETALK;
1320 iface->i_addr.sat_addr.s_net = net;
1321 iface->i_addr.sat_addr.s_node = node;
1323 nr.nr_phase = phase;
1324 nr.nr_firstnet = first;
1325 nr.nr_lastnet = last;
1326 memcpy( iface->i_addr.sat_zero, &nr, sizeof( struct netrange ));
1328 if ( ifconfig( iface->i_name, SIOCSIFADDR, &iface->i_addr )) {
1329 LOG(log_error, logtype_default, "setifaddr: %s (%u-%u): %s. try specifying a \
1330 smaller net range.", iface->i_name, ntohs(first), ntohs(last), strerror(errno));
1333 if ( ifconfig( iface->i_name, SIOCGIFADDR, &iface->i_addr )) {
1334 LOG(log_error, logtype_default, "getifaddr: %s: %s", iface->i_name, strerror(errno) );
1339 i = 1; /* enable broadcasts */
1341 LOG(log_info, logtype_default, "setsockopt incompatible w/ Solaris STREAMS module.");
1342 #endif /* __svr4__ */
1343 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1344 if (( ap->ap_fd = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1345 LOG(log_error, logtype_default, "socket: %s", strerror(errno) );
1349 setsockopt(ap->ap_fd, SOL_SOCKET, SO_BROADCAST, &i, sizeof(i));
1350 #endif /* ! __svr4 */
1352 memset( &sat, 0, sizeof( struct sockaddr_at ));
1354 sat.sat_len = sizeof( struct sockaddr_at );
1356 sat.sat_family = AF_APPLETALK;
1357 sat.sat_addr.s_net = iface->i_addr.sat_addr.s_net;
1358 sat.sat_addr.s_node = iface->i_addr.sat_addr.s_node;
1359 sat.sat_port = ap->ap_port;
1361 if ( bind( ap->ap_fd, (struct sockaddr *)&sat,
1362 sizeof( struct sockaddr_at )) < 0 ) {
1363 LOG(log_error, logtype_default, "bind %u.%u:%u: %s",
1364 ntohs( sat.sat_addr.s_net ),
1365 sat.sat_addr.s_node, sat.sat_port, strerror(errno) );
1367 /* remove all interfaces if we have a problem with bind */
1368 for (iface = interfaces; iface; iface = iface->i_next) {
1369 if (ifconfig( iface->i_name, SIOCDIFADDR, &iface->i_addr )) {
1370 #ifdef SIOCATALKDIFADDR
1371 #if (SIOCDIFADDR != SIOCATALKDIFADDR)
1372 ifconfig( iface->i_name, SIOCATALKDIFADDR, &iface->i_addr );
1373 #endif /* SIOCDIFADDR != SIOCATALKDIFADDR */
1374 #endif /* SIOCATALKDIFADDR */
1377 #endif /* SIOCDIFADDR */
1382 /* recalculate nfds and fds */
1384 for ( nfds = 0, iface = interfaces; iface; iface = iface->i_next ) {
1385 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1386 FD_SET( ap->ap_fd, &fds );
1387 if ( ap->ap_fd > nfds ) {
1395 int ifconfig( iname, cmd, sa )
1398 struct sockaddr_at *sa;
1403 memset(&ifr, 0, sizeof(ifr));
1404 strcpy( ifr.ifr_name, iname );
1405 ifr.ifr_addr = *(struct sockaddr *)sa;
1407 if (( s = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1410 if ( ioctl( s, cmd, &ifr ) < 0 ) {
1415 if ( cmd == SIOCGIFADDR ) {
1416 *(struct sockaddr *)sa = ifr.ifr_addr;
1421 void dumpconfig( iface )
1422 struct interface *iface;
1426 printf( "%s", iface->i_name );
1427 if ( iface->i_flags & IFACE_RSEED ) {
1428 printf( " -router" );
1429 } else if ( iface->i_flags & IFACE_SEED ) {
1433 if ( iface->i_flags & IFACE_DONTROUTE)
1434 printf( " -dontroute");
1436 printf( " -phase" );
1437 if ( iface->i_flags & IFACE_PHASE1 ) {
1442 printf( " -net %d", ntohs( iface->i_rt->rt_firstnet ));
1443 if ( iface->i_rt->rt_lastnet != iface->i_rt->rt_firstnet ) {
1444 printf( "-%d", ntohs( iface->i_rt->rt_lastnet ));
1446 printf( " -addr %u.%u", ntohs( iface->i_addr.sat_addr.s_net ),
1447 iface->i_addr.sat_addr.s_node );
1448 printf( " -caddr %u.%u", ntohs( iface->i_caddr.sat_addr.s_net ),
1449 iface->i_caddr.sat_addr.s_node );
1450 for ( l = iface->i_rt->rt_zt; l; l = l->l_next ) {
1451 printf( " -zone %.*s", ((struct ziptab *)l->l_data)->zt_len,
1452 ((struct ziptab *)l->l_data)->zt_name );
1460 struct interface *iface;
1461 struct rtmptab *rtmp;
1465 for ( iface = interfaces; iface; iface = iface->i_next ) {
1466 for ( rtmp = iface->i_rt; rtmp; rtmp = rtmp->rt_inext ) {
1467 if ( rtmp->rt_gate == 0 ) {
1468 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
1469 printf( "%u-%u", ntohs( rtmp->rt_firstnet ),
1470 ntohs( rtmp->rt_lastnet ));
1472 printf( "%u", ntohs( rtmp->rt_firstnet ));
1475 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
1476 printf( "%u.%u for %u-%u",
1477 ntohs( rtmp->rt_gate->g_sat.sat_addr.s_net ),
1478 rtmp->rt_gate->g_sat.sat_addr.s_node,
1479 ntohs( rtmp->rt_firstnet ),
1480 ntohs( rtmp->rt_lastnet ));
1482 printf( "%u.%u for %u",
1483 ntohs( rtmp->rt_gate->g_sat.sat_addr.s_net ),
1484 rtmp->rt_gate->g_sat.sat_addr.s_node,
1485 ntohs( rtmp->rt_firstnet ));
1489 if ( rtmp->rt_iprev == 0 && rtmp != iface->i_rt ) {
1493 for ( l = rtmp->rt_zt; l; l = l->l_next ) {
1494 zt = (struct ziptab *)l->l_data;
1495 printf( " %.*s", zt->zt_len, zt->zt_name );
1508 struct interface *iface;
1509 struct rtmptab *rtmp;
1513 for ( zt = ziptab; zt; zt = zt->zt_next ) {
1514 printf( "%.*s", zt->zt_len, zt->zt_name );
1515 for ( l = zt->zt_rt; l; l = l->l_next ) {
1516 rtmp = (struct rtmptab *)l->l_data;
1517 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
1518 printf( " %u-%u", ntohs( rtmp->rt_firstnet ),
1519 ntohs( rtmp->rt_lastnet ));
1521 printf( " %u", ntohs( rtmp->rt_firstnet ));
1523 if ( rtmp->rt_iprev == 0 && rtmp->rt_gate != 0 ) {