2 * $Id: main.c,v 1.19 2009-01-16 18:21:16 morgana 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>
16 #include <sys/resource.h>
17 #include <sys/ioctl.h>
20 #include <sys/types.h>
21 #ifdef HAVE_SYS_WAIT_H
23 #endif /* HAVE_SYS_WAIT_H */
25 #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
26 #endif /* ! WEXITSTATUS */
28 #define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
29 #endif /* ! WIFEXITED */
31 #define WIFSTOPPED(status) (((status) & 0xff) == 0x7f)
37 #include <net/route.h>
40 #include <net/route.h>
42 #include <netinet/in.h>
45 #include <atalk/logger.h>
53 #include <netatalk/endian.h>
54 #include <netatalk/at.h>
55 #include <atalk/compat.h>
56 #include <atalk/zip.h>
57 #include <atalk/rtmp.h>
58 #include <atalk/ddp.h>
59 #include <atalk/atp.h>
60 #include <atalk/paths.h>
61 #include <atalk/util.h>
64 #include <sys/sockio.h>
68 #include "interface.h"
76 /* Forward Declarations */
77 int ifconfig(const char *iname, unsigned long cmd, struct sockaddr_at *sa);
79 /* FIXME/SOCKLEN_T: socklen_t is a unix98 feature */
81 #define SOCKLEN_T unsigned int
82 #endif /* SOCKLEN_T */
85 #define WEXITSTATUS(x) ((x).w_retcode)
86 #endif /* WEXITSTATUS */
88 /* linux has a special ioctl for appletalk device destruction. as of
89 * 2.1.57, SIOCDIFADDR works w/ linux. okay, we need to deal with the
90 * fact that SIOCDIFADDR may be defined on linux despite the fact that
92 #if !defined(SIOCDIFADDR) && defined(SIOCATALKDIFADDR)
93 #define SIOCDIFADDR SIOCATALKDIFADDR
96 #define elements(a) (sizeof(a)/sizeof((a)[0]))
100 extern int rtmp_packet();
101 extern int nbp_packet();
102 extern int aep_packet();
103 extern int zip_packet();
107 static struct atserv atserv[] = {
108 { "rtmp", 1, rtmp_packet }, /* 0 */
109 { "nbp", 2, nbp_packet }, /* 1 */
110 { "echo", 4, aep_packet }, /* 2 */
111 { "zip", 6, zip_packet }, /* 3 */
113 static int atservNATSERV = elements( atserv );
115 struct interface *interfaces = NULL, *ciface = NULL;
117 int debug = 0, quiet = 0, chatty = 0;
118 char *configfile = NULL;
119 int ziptimeout = 0, transition = 0;
120 int stabletimer, stable = 0, newrtmpdata = 0, noparent = 0;
121 static int ninterfaces;
122 int defphase = IFACE_PHASE2;
125 char Packet[ PKTSZ ];
126 char *version = VERSION;
127 static char *pidfile = _PATH_ATALKDLOCK;
132 int readconf( char * );
133 int getifconf( void );
134 int writeconf( char * );
136 /* this is the messiest of the bunch as atalkd can exit pretty much
137 * everywhere. we delete interfaces here instead of in as_down. */
138 static void atalkd_exit(const int i)
141 struct interface *iface;
143 for (iface = interfaces; iface; iface = iface->i_next) {
144 if (ifconfig( iface->i_name, SIOCDIFADDR, &iface->i_addr)) {
145 #ifdef SIOCATALKDIFADDR
146 #if (SIOCDIFADDR != SIOCATALKDIFADDR)
147 if (!ifconfig(iface->i_name, SIOCATALKDIFADDR, &iface->i_addr))
149 #endif /* SIOCDIFADDR != SIOCATALKDIFADDR */
150 #endif /* SIOCATALKIFADDR */
151 LOG(log_error, logtype_atalkd, "difaddr(%u.%u): %s",
152 ntohs(iface->i_addr.sat_addr.s_net),
153 iface->i_addr.sat_addr.s_node, strerror(errno));
156 if (!(iface->i_flags & IFACE_WASALLMULTI) && (iface->i_flags & IFACE_ALLMULTI))
157 ifsetallmulti(iface->i_name, 0);
160 #endif /* SOPCDOFADDR */
162 server_unlock(pidfile);
167 static void as_timer(int sig _U_)
169 struct sockaddr_at sat;
172 struct rtmp_tuple rt;
173 struct atport *ap, *zap, *rap;
174 struct interface *iface, *iface2;
175 struct gate *gate, *fgate = NULL;
176 struct rtmptab *rtmp, *frtmp;
178 char *data, *end, packet[ ATP_BUFSIZ ];
184 memset(&sat, 0, sizeof( struct sockaddr_at ));
185 for ( iface = interfaces; iface; iface = iface->i_next ) {
186 if ( iface->i_flags & IFACE_LOOPBACK ) {
189 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
190 if ( ap->ap_packet == zip_packet ) {
193 if ( ap->ap_packet == rtmp_packet ) {
198 if (( iface->i_flags & ( IFACE_ADDR|IFACE_CONFIG|IFACE_NOROUTER )) ==
200 if ( iface->i_time < 3 ) {
201 if ( iface->i_flags & IFACE_PHASE1 ) {
202 if (rtmp_request( iface ) < 0) {
203 LOG(log_error, logtype_atalkd, "rtmp_request: %s", strerror(errno));
208 if (zip_getnetinfo( iface ) < 0) {
209 LOG(log_error, logtype_atalkd, "zip_getnetinfo: %s", strerror(errno));
216 iface->i_flags |= IFACE_NOROUTER;
217 if ((iface->i_flags & IFACE_ISROUTER)) {
218 if (( iface->i_flags & IFACE_SEED ) == 0 ) {
220 * No seed info, and we've got multiple interfaces.
223 LOG(log_info, logtype_atalkd,
224 "as_timer multiple interfaces, no seed" );
225 LOG(log_info, logtype_atalkd, "as_timer can't configure %s",
227 LOG(log_info, logtype_atalkd, "as_timer waiting for router" );
232 * Complete configuration for iface, and boot next
235 iface->i_flags |= IFACE_CONFIG;
236 for ( zt = iface->i_czt; zt; zt = zt->zt_next ) {
237 if (addzone( iface->i_rt, zt->zt_len,
239 LOG(log_error, logtype_atalkd, "addzone: %s", strerror(errno));
243 if ( iface->i_rt->rt_zt ) {
244 iface->i_rt->rt_flags &= ~RTMPTAB_ZIPQUERY;
245 iface->i_rt->rt_flags |= RTMPTAB_HASZONES;
247 if ( iface->i_flags & IFACE_PHASE1 ) {
248 LOG(log_info, logtype_atalkd,
249 "as_timer configured %s phase 1 from seed",
251 setaddr( iface, IFACE_PHASE1,
252 iface->i_caddr.sat_addr.s_net,
253 iface->i_addr.sat_addr.s_node,
254 iface->i_caddr.sat_addr.s_net,
255 iface->i_caddr.sat_addr.s_net );
257 LOG(log_info, logtype_atalkd,
258 "as_timer configured %s phase 2 from seed",
262 if ( looproute( iface, RTMP_ADD )) { /* -1 or 1 */
263 LOG(log_error, logtype_atalkd,
264 "as_timer: can't route %u.%u to loop: %s",
265 ntohs( iface->i_addr.sat_addr.s_net ),
266 iface->i_addr.sat_addr.s_node,
270 if ( iface == ciface ) {
271 ciface = ciface->i_next;
277 * Configure for no router operation. Wait for a route
278 * to become available in rtmp_packet().
280 LOG(log_info, logtype_atalkd, "config for no router" );
282 if ( iface->i_flags & IFACE_PHASE2 ) {
283 iface->i_rt->rt_firstnet = 0;
284 iface->i_rt->rt_lastnet = htons( STARTUP_LASTNET );
285 setaddr( iface, IFACE_PHASE2,
286 iface->i_addr.sat_addr.s_net,
287 iface->i_addr.sat_addr.s_node,
288 0, htons( STARTUP_LASTNET ));
290 if ( looproute( iface, RTMP_ADD ) ) { /* -1 or 1 */
291 LOG(log_error, logtype_atalkd,
292 "as_timer: can't route %u.%u to loopback: %s",
293 ntohs( iface->i_addr.sat_addr.s_net ),
294 iface->i_addr.sat_addr.s_node,
299 if ( iface == ciface ) {
300 ciface = ciface->i_next;
307 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
309 free( (caddr_t)fgate );
314 data = packet + 1 + sizeof( struct ziphdr );
315 end = packet + sizeof( packet );
318 sat.sat_port = zap->ap_port;
321 * Perform timeouts on routers. If we've only got one
322 * interface, we'll use these timeouts to decide that
323 * our zone has gone away.
325 if ( ++gate->g_state >= RTMPTAB_BAD ) {
326 LOG(log_info, logtype_atalkd, "as_timer gateway %u.%u down",
327 ntohs( gate->g_sat.sat_addr.s_net ),
328 gate->g_sat.sat_addr.s_node );
331 frtmp = rtmp->rt_next;
332 if ( rtmp->rt_hops == RTMPHOPS_POISON ||
333 rtmp->rt_iprev == 0 ) {
336 rtmp->rt_hops = RTMPHOPS_POISON;
337 if ((cc = rtmp_replace( rtmp )) < 0) {
338 LOG(log_error, logtype_atalkd, "rtmp_replace: %s", strerror(errno));
342 gate->g_state = rtmp->rt_state = RTMPTAB_GOOD;
347 if ( gate->g_rt == 0 ) {
348 if ( gate->g_prev == 0 ) {
349 gate->g_iface->i_gate = gate->g_next;
351 gate->g_prev->g_next = gate->g_next;
353 if ( gate->g_next != 0 ) {
354 gate->g_next->g_prev = gate->g_prev;
356 fgate = gate; /* can't free here, just mark it */
359 * If this is the last router on the only interface,
360 * reconfigure our netrange. By marking the interface
361 * as having no router, we will notice when a router
364 * XXX: actually, we always reconfigure an interface
365 * if we're not a seed router.
368 if ( gate->g_iface->i_gate == 0 &&
369 ((iface->i_flags & IFACE_SEED) == 0)) {
370 gate->g_iface->i_flags |= IFACE_NOROUTER;
371 gate->g_iface->i_flags &= ~IFACE_CONFIG;
373 /* get rid of any zones associated with this iface */
374 if (gate->g_iface->i_rt->rt_zt) {
375 rtmp_delzonemap(gate->g_iface->i_rt);
376 gate->g_iface->i_rt->rt_flags &= ~RTMPTAB_HASZONES;
379 LOG(log_info, logtype_atalkd, "as_timer last gateway down" );
381 /* Set netrange to 0-fffe. */
382 if ( gate->g_iface->i_flags & IFACE_PHASE2 ) {
383 gate->g_iface->i_rt->rt_firstnet = 0;
384 gate->g_iface->i_rt->rt_lastnet =
385 htons( STARTUP_LASTNET );
386 setaddr( iface, IFACE_PHASE2,
387 iface->i_addr.sat_addr.s_net,
388 iface->i_addr.sat_addr.s_node,
389 0, htons( STARTUP_LASTNET ));
396 * If we don't have a zone for our interface yet, ask for
397 * it from any router (all routers) on the interface.
399 if (( iface->i_rt->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
400 iface->i_rt->rt_flags |= RTMPTAB_ZIPQUERY;
401 memcpy( data, &iface->i_rt->rt_firstnet, sizeof( u_short ));
402 data += sizeof( u_short );
409 * Delete old routing tuples.
411 if ( rtmp->rt_state != RTMPTAB_PERM ) {
416 * We've not been updated for this route in a while. If
417 * it's not in use, go ahead and remove it. If it is in
418 * use, mark the route as down (POISON), and look for a
419 * better route. If one is found, delete this route and use
420 * the new one. If it's not found, mark the route as GOOD
421 * (so we'll propogate our poison) and delete it the next
422 * time it becomes BAD.
424 if ( rtmp->rt_state >= RTMPTAB_BAD ) {
425 frtmp = rtmp->rt_next;
426 if ( rtmp->rt_iprev == 0 ) { /* not in use */
428 } else { /* in use */
429 if ( rtmp->rt_hops == RTMPHOPS_POISON ) {
432 rtmp->rt_hops = RTMPHOPS_POISON;
433 if ((cc = rtmp_replace( rtmp )) < 0) {
434 LOG(log_error, logtype_atalkd, "rtmp_replace: %s", strerror(errno));
438 rtmp->rt_state = RTMPTAB_GOOD;
448 if ( rtmp->rt_iprev &&
449 ( rtmp->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
450 if ( data + sizeof( u_short ) > end || n == 255 ) {
451 /* send what we've got */
452 zh.zh_op = ZIPOP_QUERY;
456 *data++ = DDPTYPE_ZIP;
457 memcpy( data, &zh, sizeof( struct ziphdr ));
459 if ( sendto( zap->ap_fd, packet, cc, 0,
460 (struct sockaddr *)&sat,
461 sizeof( struct sockaddr_at )) < 0 ) {
462 LOG(log_error, logtype_atalkd, "as_timer sendto: %s", strerror(errno) );
467 data = packet + 1 + sizeof( struct ziphdr );
468 end = packet + sizeof( packet );
472 * rt_nzq is number of ZIP Queries we've issued for a
473 * given netrange. If we've got ziptimeout on, we
474 * will only ask 3 times for any given netrange.
475 * Interestingly enough, since rt_nzq is a u_char,
476 * it will overflow after a while. This means we will
477 * periodically ask for nets that we've decided not to
478 * ask about, and warn that we can't get it's zone.
480 if ( rtmp->rt_nzq++ == 3 ) {
481 LOG(log_info, logtype_atalkd, "as_timer can't get zone for %u",
482 ntohs( rtmp->rt_firstnet ));
484 if ( rtmp->rt_nzq > 3 ) {
486 rtmp = rtmp->rt_next;
492 rtmp->rt_flags |= RTMPTAB_ZIPQUERY;
493 memcpy( data, &rtmp->rt_firstnet, sizeof( u_short ));
494 data += sizeof( u_short );
497 rtmp = rtmp->rt_next;
500 /* send what we've got */
502 zh.zh_op = ZIPOP_QUERY;
506 *data++ = DDPTYPE_ZIP;
507 memcpy( data, &zh, sizeof( struct ziphdr ));
509 if ( sendto( zap->ap_fd, packet, cc, 0, (struct sockaddr *)&sat,
510 sizeof( struct sockaddr_at )) < 0 ) {
511 LOG(log_error, logtype_atalkd, "as_timer sendto: %s", strerror(errno) );
516 free( (caddr_t)fgate );
521 * Send RTMP broadcasts if we have multiple interfaces or our
522 * interface is configured as a router.
524 if ((iface->i_flags & IFACE_ISROUTER)) {
526 sat.sat_len = sizeof( struct sockaddr_at );
528 sat.sat_family = AF_APPLETALK;
529 sat.sat_addr.s_net = ATADDR_ANYNET;
530 sat.sat_addr.s_node = ATADDR_BCAST;
531 sat.sat_port = rap->ap_port;
534 end = data + sizeof( packet );
535 *data++ = DDPTYPE_RTMPRD;
536 rh.rh_net = iface->i_addr.sat_addr.s_net;
538 rh.rh_node = iface->i_addr.sat_addr.s_node;
539 memcpy( data, &rh, sizeof( struct rtmp_head ));
540 data += sizeof( struct rtmp_head );
544 if ( iface->i_flags & IFACE_PHASE1 ) {
547 memcpy( data, &rt, SZ_RTMPTUPLE );
548 data += SZ_RTMPTUPLE;
550 rt.rt_net = iface->i_rt->rt_firstnet;
552 memcpy( data, &rt, SZ_RTMPTUPLE );
553 data += SZ_RTMPTUPLE;
555 rt.rt_net = iface->i_rt->rt_lastnet;
557 memcpy( data, &rt, SZ_RTMPTUPLE );
558 data += SZ_RTMPTUPLE;
561 for ( iface2 = interfaces; iface2; iface2 = iface2->i_next ) {
563 /* XXX: there used to be a bit checking against iface ==
564 iface2. also, we don't want to send an rtmp broadcast
565 to an interface that doesn't want it. */
566 if ((( iface2->i_flags & IFACE_CONFIG ) == 0) ||
567 ((iface2->i_flags & IFACE_ISROUTER) == 0)) {
571 * Fill in tuples. Always send the same thing, regardless
572 * of the phase of the destination. Routers who don't
573 * understand extended rtmp packets will toss extended
574 * tuples because their distance will have the high bit set.
576 for ( rtmp = iface2->i_rt; rtmp; rtmp = rtmp->rt_inext ) {
577 /* don't broadcast routes we have no zone for */
578 if ( rtmp->rt_zt == 0 ||
579 ( rtmp->rt_flags & RTMPTAB_ZIPQUERY ) ||
580 ( rtmp->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
584 if ((( rtmp->rt_flags & RTMPTAB_EXTENDED ) &&
585 data + 2 * SZ_RTMPTUPLE > end ) ||
586 data + SZ_RTMPTUPLE > end ) {
587 if ( sendto( rap->ap_fd, packet, data - packet, 0,
588 (struct sockaddr *)&sat,
589 sizeof( struct sockaddr_at )) < 0 ) {
590 LOG(log_error, logtype_atalkd, "as_timer sendto %u.%u (%u): %s",
591 ntohs( sat.sat_addr.s_net ),
593 ntohs( iface->i_rt->rt_firstnet ),
597 if ( iface->i_flags & IFACE_PHASE2 ) {
598 data = packet + 1 + sizeof( struct rtmp_head ) +
601 data = packet + 1 + sizeof( struct rtmp_head ) +
607 rt.rt_net = rtmp->rt_firstnet;
608 rt.rt_dist = rtmp->rt_hops;
609 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
612 memcpy( data, &rt, SZ_RTMPTUPLE );
613 data += SZ_RTMPTUPLE;
615 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
616 rt.rt_net = rtmp->rt_lastnet;
618 memcpy( data, &rt, SZ_RTMPTUPLE );
619 data += SZ_RTMPTUPLE;
627 if ( sendto( rap->ap_fd, packet, data - packet, 0,
628 (struct sockaddr *)&sat,
629 sizeof( struct sockaddr_at )) < 0 ) {
630 LOG(log_error, logtype_atalkd, "as_timer sendto %u.%u (%u): %s",
631 ntohs( sat.sat_addr.s_net ),
633 ntohs( iface->i_rt->rt_firstnet ),
641 * Check if we're stable. Each time we configure an interface, we
642 * sent stabletimer to UNSTABLE. If stabletimer ever gets to
643 * STABLEANYWAY, we give up and decide to "be" stable anyway.
644 * Normally, we wait for stabletimer get <= STABLE with no new rtmp
645 * data and all zip data complete.
648 if ( stabletimer <= STABLE && !newrtmpdata && !sentzipq ) {
649 /* write out config file */
651 writeconf( configfile );
653 if ( stabletimer-- <= STABLEANYWAY ) {
659 if ( stable && !noparent ) {
661 LOG(log_info, logtype_atalkd, "ready %d/%d/%d", stabletimer, newrtmpdata,
665 * Seems like we could get here more than once...
667 if ( kill( getpid(), SIGSTOP ) < 0 ) {
668 LOG(log_error, logtype_atalkd, "as_timer: kill-self failed!" );
682 * Consistency check...
686 struct rtmptab *rtmp;
687 struct list *lr, *lz;
690 for ( zt = ziptab; zt; zt = zt->zt_next ) {
691 for ( lr = zt->zt_rt; lr; lr = lr->l_next ) {
692 rtmp = (struct rtmptab *)lr->l_data;
693 if ( rtmp->rt_iprev == 0 && rtmp->rt_gate != 0 ) {
694 LOG(log_error, logtype_atalkd, "%.*s has %u-%u (unused)",
695 zt->zt_len, zt->zt_name, ntohs( rtmp->rt_firstnet ),
696 ntohs( rtmp->rt_lastnet ));
699 for ( lz = rtmp->rt_zt; lz; lz = lz->l_next ) {
700 if ( zt == (struct ziptab *)lz->l_data ) {
705 LOG(log_error, logtype_atalkd, "no map from %u-%u to %.*s",
706 ntohs( rtmp->rt_firstnet ),
707 ntohs( rtmp->rt_lastnet ),
708 zt->zt_len, zt->zt_name );
716 #if !defined( ibm032 ) && !defined( _IBMR2 )
718 #endif /* ! ibm032 && ! _IBMR2 */
721 struct interface *iface;
728 if (( rtmpdebug = fopen( _PATH_ATALKDEBUG, "w" )) == NULL ) {
729 LOG(log_error, logtype_atalkd, "rtmp: %s", strerror(errno) );
732 for ( iface = interfaces; iface; iface = iface->i_next ) {
733 fprintf( rtmpdebug, "interface %s %u.%u ", iface->i_name,
734 ntohs( iface->i_addr.sat_addr.s_net ),
735 iface->i_addr.sat_addr.s_node );
736 if ( iface->i_flags & IFACE_PHASE1 ) {
737 putc( '1', rtmpdebug );
739 if ( iface->i_flags & IFACE_PHASE2 ) {
740 putc( '2', rtmpdebug );
742 if ( iface->i_flags & IFACE_RSEED ) {
743 putc( 'R', rtmpdebug );
745 if ( iface->i_flags & IFACE_SEED ) {
746 putc( 'S', rtmpdebug );
748 if ( iface->i_flags & IFACE_DONTROUTE ) {
749 putc( 'D', rtmpdebug );
751 if ( iface->i_flags & IFACE_ADDR ) {
752 putc( 'A', rtmpdebug );
754 if ( iface->i_flags & IFACE_CONFIG ) {
755 putc( 'C', rtmpdebug );
757 if ( iface->i_flags & IFACE_NOROUTER ) {
758 putc( 'N', rtmpdebug );
760 if ( iface->i_flags & IFACE_LOOP ) {
761 putc( 'L', rtmpdebug );
763 putc( '\n', rtmpdebug );
766 fprintf( rtmpdebug, "\t%u-%u ",
767 ntohs( iface->i_rt->rt_firstnet ),
768 ntohs( iface->i_rt->rt_lastnet ));
769 if ( iface->i_rt->rt_flags & RTMPTAB_ZIPQUERY ) {
770 putc( 'q', rtmpdebug );
772 if ( iface->i_rt->rt_flags & RTMPTAB_HASZONES ) {
773 putc( 'z', rtmpdebug );
775 if ( iface->i_rt->rt_flags & RTMPTAB_EXTENDED ) {
776 putc( 'x', rtmpdebug );
778 putc( 'i', rtmpdebug );
779 for ( l = iface->i_rt->rt_zt; l; l = l->l_next ) {
780 zt = (struct ziptab *)l->l_data;
781 fprintf( rtmpdebug, " '%.*s'", zt->zt_len, zt->zt_name );
783 fprintf( rtmpdebug, "\n" );
786 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
787 fprintf( rtmpdebug, "gate %u.%u %X\n",
788 ntohs( gate->g_sat.sat_addr.s_net ),
789 gate->g_sat.sat_addr.s_node, gate->g_state );
790 for ( rt = gate->g_rt; rt; rt = rt->rt_next ) {
791 fprintf( rtmpdebug, "\t%u-%u ", ntohs( rt->rt_firstnet ),
792 ntohs( rt->rt_lastnet ));
793 if ( rt->rt_flags & RTMPTAB_ZIPQUERY ) {
794 putc( 'q', rtmpdebug );
796 if ( rt->rt_flags & RTMPTAB_HASZONES ) {
797 putc( 'z', rtmpdebug );
799 if ( rt->rt_flags & RTMPTAB_EXTENDED ) {
800 putc( 'x', rtmpdebug );
802 if ( rt->rt_iprev ) {
803 putc( 'i', rtmpdebug );
805 for ( l = rt->rt_zt; l; l = l->l_next ) {
806 zt = (struct ziptab *)l->l_data;
807 fprintf( rtmpdebug, " '%.*s'", zt->zt_len, zt->zt_name );
809 fprintf( rtmpdebug, "\n" );
818 * Called when SIGTERM is recieved. Remove all routes and then exit.
820 #if !defined( ibm032 ) && !defined( _IBMR2 )
822 #endif /* ! ibm032 && ! _IBMR2 */
825 struct interface *iface;
829 for ( iface = interfaces; iface; iface = iface->i_next ) {
830 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
831 for ( rt = gate->g_rt; rt; rt = rt->rt_next ) {
832 if ( rt->rt_iprev ) {
833 if ( gateroute( RTMP_DEL, rt ) < 0 ) {
834 LOG(log_error, logtype_atalkd, "as_down remove %u-%u failed: %s",
835 ntohs( rt->rt_firstnet ),
836 ntohs( rt->rt_lastnet ),
842 if ( iface->i_flags & IFACE_LOOP ) {
843 if (looproute( iface, RTMP_DEL )) {
844 LOG(log_error, logtype_atalkd, "as_down remove %s %u.%u failed: %s",
845 iface->i_name, ntohs( iface->i_addr.sat_addr.s_net ),
846 iface->i_addr.sat_addr.s_node,
852 LOG(log_info, logtype_atalkd, "done" );
863 struct sockaddr_at sat;
866 sigset_t signal_set, old_set;
868 struct interface *iface;
876 while (( c = getopt( ac, av, "12qsdtf:P:v" )) != EOF ) {
879 defphase = IFACE_PHASE1;
883 defphase = IFACE_PHASE2;
894 case 'q' : /* don't seed */
898 case 's' : /* seed */
902 case 't' : /* transition */
906 case 'P' : /* pid file */
910 case 'v' : /* version */
911 printf( "atalkd (version %s)\n", version );
916 fprintf( stderr, "Unknown option -- '%c'\n", c );
920 if ( optind != ac ) {
921 fprintf( stderr, "Too many arguments.\n" );
925 if (( prog = strrchr( av[ 0 ], '/' )) == NULL ) {
932 * Configure loop back address first, so appearances of "lo0" in
933 * the config file fail. Also insures that lo0 gets configured,
934 * even if there's some hangup during configuration of some
937 if (( interfaces = newiface( LOOPIFACE )) == NULL ) {
938 perror( "newiface" );
941 interfaces->i_flags |= IFACE_PHASE2 | IFACE_LOOPBACK;
944 * Check our initial configuration before we fork. This way we can
945 * complain about syntax errors on stdout.
947 * Basically, if we're going to read our config file, we should read
948 * it and initialize our data structures. If we're not going to read
949 * our config file, use GIFCONF to initialize our data structures.
951 if ( readconf( configfile ) < 0 && getifconf() < 0 ) {
952 fprintf( stderr, "%s: can't get interfaces, exiting.\n", prog );
956 /* we need to count up our interfaces so that we can simplify things
957 * later. we also need to figure out if we have more than one interface
958 * that is routing. */
959 for (i = 0, ninterfaces = 0, iface = interfaces; iface;
960 iface=iface->i_next) {
961 if (iface->i_flags & IFACE_DONTROUTE)
965 i = ninterfaces - i; /* number of routable interfaces */
968 * At this point, we have (at least partially) initialized data
969 * structures. Fill in what we can and verify that nothing is obviously
972 for (iface = interfaces; iface; iface = iface->i_next) {
973 /* Apply the default phase */
974 if (( iface->i_flags & IFACE_PHASE1 ) == 0 &&
975 ( iface->i_flags & IFACE_PHASE2 ) == 0 ) {
976 iface->i_flags |= defphase;
979 /* set up router flag information. if we have multiple interfaces
980 * and DONTROUTE isn't set, set up ROUTER. i is the number of
981 * interfaces that don't have the DONTROUTE flag set. */
982 if ((i > IFBASE) && ((iface->i_flags & IFACE_DONTROUTE) == 0)) {
983 iface->i_flags |= IFACE_ISROUTER;
986 /* Set default addresses */
987 if ( iface->i_rt == NULL ) {
988 if (( iface->i_rt = newrt(iface)) == NULL ) {
993 if ( iface->i_flags & IFACE_PHASE1 ) {
994 iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet =
995 iface->i_caddr.sat_addr.s_net;
997 if ( iface->i_caddr.sat_addr.s_net != ATADDR_ANYNET ||
998 ( iface->i_flags & IFACE_LOOPBACK )) {
999 iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet =
1000 iface->i_caddr.sat_addr.s_net;
1002 iface->i_rt->rt_firstnet = htons( STARTUP_FIRSTNET );
1003 iface->i_rt->rt_lastnet = htons( STARTUP_LASTNET );
1008 if (( iface->i_flags & IFACE_PHASE1 ) == 0 ) {
1009 iface->i_rt->rt_flags |= RTMPTAB_EXTENDED;
1012 if ( iface->i_caddr.sat_addr.s_net == ATADDR_ANYNET ) {
1013 iface->i_caddr.sat_addr.s_net = iface->i_rt->rt_firstnet;
1017 dumpconfig( iface ); /* probably needs args */
1022 * A little consistency check...
1024 if ( ninterfaces < IFBASE ) {
1025 fprintf( stderr, "%s: zero interfaces, exiting.\n", prog );
1030 * Set process name for logging
1033 set_processname("atalkd");
1035 /* do this here so that we can use ifconfig */
1037 if ( plumb() < 0 ) {
1038 fprintf(stderr, "can't establish STREAMS plumbing, exiting.\n" );
1041 #endif /* __svr4__ */
1043 /* delete pre-existing interface addresses. */
1045 for (iface = interfaces; iface; iface = iface->i_next) {
1046 if (ifconfig(iface->i_name, SIOCDIFADDR, &iface->i_addr)) {
1047 #ifdef SIOCATALKDIFADDR
1048 #if (SIOCDIFADDR != SIOCATALKDIFADDR)
1049 ifconfig(iface->i_name, SIOCATALKDIFADDR, &iface->i_addr);
1050 #endif /* SIOCDIFADDR != SIOCATALKDIFADDR */
1051 #endif /* SIOCATALKDIFADDR */
1054 #endif /* SIOCDIFADDR */
1057 * Disassociate. The child will send itself a signal when it is
1058 * stable. This indicates that other processes may begin using
1061 switch (i = server_lock("atalkd", pidfile, debug)) {
1066 default: /* parent */
1068 * Wait for the child to send itself a SIGSTOP, after which
1069 * we send it a SIGCONT and exit ourself.
1071 if ( wait3( &status, WUNTRACED, (struct rusage *)0 ) != i) {
1072 perror( "wait3" ); /* Child died? */
1075 if ( !WIFSTOPPED( status )) {
1076 fprintf( stderr, "AppleTalk not up! Check your syslog for the reason." );
1077 if ( WIFEXITED( status )) {
1078 fprintf( stderr, " Child exited with %d.\n",
1079 WEXITSTATUS( status ));
1081 fprintf( stderr, " Child died.\n" );
1085 if ( kill(i, SIGCONT ) < 0 ) {
1093 openlog( prog, LOG_PID );
1095 set_processname(prog);
1096 syslog_setup(log_debug, logtype_default, logoption_pid, logfacility_daemon );
1099 LOG(log_info, logtype_atalkd, "restart (%s)", version );
1102 * Socket for use in routing ioctl()s. Can't add routes to our
1103 * interfaces until we have our routing socket.
1106 if (( rtfd = socket( PF_ROUTE, SOCK_RAW, AF_APPLETALK )) < 0 ) {
1107 LOG(log_error, logtype_atalkd, "route socket: %s", strerror(errno) );
1110 if ( shutdown( rtfd, 0 ) < 0 ) {
1111 LOG(log_error, logtype_atalkd, "route shutdown: %s", strerror(errno) );
1115 if (( rtfd = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1116 LOG(log_error, logtype_atalkd, "route socket: %s", strerror(errno) );
1121 ciface = interfaces;
1124 memset(&sv, 0, sizeof(sv));
1125 sv.sa_handler = as_down;
1126 sigemptyset( &sv.sa_mask );
1127 sigaddset( &sv.sa_mask, SIGUSR1 );
1128 sigaddset( &sv.sa_mask, SIGALRM );
1129 sigaddset( &sv.sa_mask, SIGTERM );
1130 sv.sa_flags = SA_RESTART;
1131 if ( sigaction( SIGTERM, &sv, NULL) < 0 ) {
1132 LOG(log_error, logtype_atalkd, "sigterm: %s", strerror(errno) );
1136 sv.sa_handler = as_debug;
1137 sigemptyset( &sv.sa_mask );
1138 sigaddset( &sv.sa_mask, SIGUSR1 );
1139 sigaddset( &sv.sa_mask, SIGALRM );
1140 sigaddset( &sv.sa_mask, SIGTERM );
1141 sv.sa_flags = SA_RESTART;
1142 if ( sigaction( SIGUSR1, &sv, NULL) < 0 ) {
1143 LOG(log_error, logtype_atalkd, "sigusr1: %s", strerror(errno) );
1147 sv.sa_handler = as_timer;
1148 sigemptyset( &sv.sa_mask );
1149 sigaddset( &sv.sa_mask, SIGUSR1 );
1150 sigaddset( &sv.sa_mask, SIGALRM );
1151 sigaddset( &sv.sa_mask, SIGTERM );
1152 sv.sa_flags = SA_RESTART;
1153 if ( sigaction( SIGALRM, &sv, NULL) < 0 ) {
1154 LOG(log_error, logtype_atalkd, "sigalrm: %s", strerror(errno) );
1158 it.it_interval.tv_sec = 10L;
1159 it.it_interval.tv_usec = 0L;
1160 it.it_value.tv_sec = 10L;
1161 it.it_value.tv_usec = 0L;
1162 if ( setitimer( ITIMER_REAL, &it, NULL) < 0 ) {
1163 LOG(log_error, logtype_atalkd, "setitimer: %s", strerror(errno) );
1167 sigemptyset( &signal_set );
1168 sigaddset(&signal_set, SIGALRM);
1170 /* don't block SIGTERM */
1171 sigaddset(&signal_set, SIGTERM);
1173 sigaddset(&signal_set, SIGUSR1);
1177 if ( select( nfds, &readfds, NULL, NULL, NULL) < 0 ) {
1178 if ( errno == EINTR ) {
1182 LOG(log_error, logtype_atalkd, "select: %s", strerror(errno) );
1187 for ( iface = interfaces; iface; iface = iface->i_next ) {
1188 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1189 if ( FD_ISSET( ap->ap_fd, &readfds )) {
1190 if ( ap->ap_packet ) {
1191 fromlen = sizeof( struct sockaddr_at );
1192 if (( c = recvfrom( ap->ap_fd, Packet, sizeof( Packet ),
1193 0, (struct sockaddr *)&sat, &fromlen )) < 0 ) {
1194 LOG(log_error, logtype_atalkd, "recvfrom: %s", strerror(errno) );
1199 printf( "packet from %u.%u on %s (%x) %d (%d)\n",
1200 ntohs( sat.sat_addr.s_net ),
1201 sat.sat_addr.s_node, iface->i_name,
1202 iface->i_flags, ap->ap_port, ap->ap_fd );
1203 bprint( Packet, c );
1206 if (sigprocmask(SIG_BLOCK, &signal_set, &old_set) < 0) {
1207 LOG(log_error, logtype_atalkd, "sigprocmask: %s", strerror(errno) );
1211 if (( *ap->ap_packet )( ap, &sat, Packet, c ) < 0) {
1212 LOG(log_error, logtype_atalkd, "ap->ap_packet: %s", strerror(errno));
1219 if (sigprocmask(SIG_SETMASK, &old_set, NULL) < 0) {
1220 LOG(log_error, logtype_atalkd, "sigprocmask old set: %s", strerror(errno) );
1232 * This code is called (from main(), as_timer(), zip_packet(),
1233 * and rtmp_packet()) to set the initial "bootstrapping" address
1236 void bootaddr( iface )
1237 struct interface *iface;
1244 if ( iface->i_flags & IFACE_ADDR ) {
1245 LOG(log_error, logtype_atalkd, "bootaddr OOPS!" );
1249 if ( iface->i_flags & IFACE_PHASE1 ) {
1250 setaddr( iface, IFACE_PHASE1, 0,
1251 iface->i_caddr.sat_addr.s_node, 0, 0 );
1253 if ( iface->i_flags & IFACE_LOOPBACK ) {
1254 iface->i_flags |= IFACE_CONFIG | IFACE_ADDR;
1255 if ( ciface == iface ) {
1256 ciface = ciface->i_next;
1260 } else if (rtmp_request( iface ) < 0) {
1261 LOG(log_error, logtype_atalkd, "bootaddr (rtmp_request): %s", strerror(errno));
1266 setaddr( iface, IFACE_PHASE2, iface->i_caddr.sat_addr.s_net,
1267 iface->i_caddr.sat_addr.s_node,
1268 iface->i_rt->rt_firstnet, iface->i_rt->rt_lastnet );
1270 if ( iface->i_flags & IFACE_LOOPBACK ) {
1271 iface->i_flags |= IFACE_CONFIG | IFACE_ADDR;
1272 if ( ciface == iface ) {
1273 ciface = ciface->i_next;
1277 } else if (zip_getnetinfo( iface ) < 0) {
1278 LOG(log_error, logtype_atalkd, "bootaddr (zip_getnetinfo): %s", strerror(errno));
1283 iface->i_flags |= IFACE_ADDR;
1284 stabletimer = UNSTABLE;
1290 * to manage the i_ports field and the fds for select().
1292 void setaddr(struct interface *iface,
1293 u_int8_t phase, u_int16_t net, u_int8_t node,
1294 u_int16_t first, u_int16_t last)
1300 struct sockaddr_at sat;
1303 if ( iface->i_ports == NULL ) { /* allocate port structures */
1304 for ( i = 0, as = atserv; i < atservNATSERV; i++, as++ ) {
1305 if (( se = getservbyname( as->as_name, "ddp" )) == NULL ) {
1306 LOG(log_info, logtype_atalkd, "%s: service unknown", as->as_name );
1308 as->as_port = ntohs( se->s_port );
1310 if (( ap = (struct atport *)malloc( sizeof( struct atport ))) ==
1312 LOG(log_error, logtype_atalkd, "malloc: %s", strerror(errno) );
1316 ap->ap_next = iface->i_ports;
1317 ap->ap_iface = iface;
1318 ap->ap_port = as->as_port;
1319 ap->ap_packet = as->as_packet;
1321 iface->i_ports = ap;
1323 } else { /* close ports */
1324 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1325 (void)close( ap->ap_fd );
1330 iface->i_addr.sat_len = sizeof( struct sockaddr_at );
1332 iface->i_addr.sat_family = AF_APPLETALK;
1333 iface->i_addr.sat_addr.s_net = net;
1334 iface->i_addr.sat_addr.s_node = node;
1336 nr.nr_phase = phase;
1337 nr.nr_firstnet = first;
1338 nr.nr_lastnet = last;
1339 memcpy( iface->i_addr.sat_zero, &nr, sizeof( struct netrange ));
1341 if ( ifconfig( iface->i_name, SIOCSIFADDR, &iface->i_addr )) {
1342 LOG(log_error, logtype_atalkd, "setifaddr: %s (%u-%u): %s. try specifying a \
1343 smaller net range.", iface->i_name, ntohs(first), ntohs(last), strerror(errno));
1346 if ( ifconfig( iface->i_name, SIOCGIFADDR, &iface->i_addr )) {
1347 LOG(log_error, logtype_atalkd, "getifaddr: %s: %s", iface->i_name, strerror(errno) );
1352 i = 1; /* enable broadcasts */
1354 /* useless message, no? */
1355 LOG(log_info, logtype_atalkd, "setsockopt incompatible w/ Solaris STREAMS module.");
1356 #endif /* __svr4__ */
1357 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1358 if (( ap->ap_fd = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1359 LOG(log_error, logtype_atalkd, "socket: %s", strerror(errno) );
1363 setsockopt(ap->ap_fd, SOL_SOCKET, SO_BROADCAST, &i, sizeof(i));
1364 #endif /* ! __svr4 */
1366 memset( &sat, 0, sizeof( struct sockaddr_at ));
1368 sat.sat_len = sizeof( struct sockaddr_at );
1370 sat.sat_family = AF_APPLETALK;
1371 sat.sat_addr.s_net = iface->i_addr.sat_addr.s_net;
1372 sat.sat_addr.s_node = iface->i_addr.sat_addr.s_node;
1373 sat.sat_port = ap->ap_port;
1375 if ( bind( ap->ap_fd, (struct sockaddr *)&sat,
1376 sizeof( struct sockaddr_at )) < 0 ) {
1377 LOG(log_error, logtype_atalkd, "bind %u.%u:%u: %s",
1378 ntohs( sat.sat_addr.s_net ),
1379 sat.sat_addr.s_node, sat.sat_port, strerror(errno) );
1381 /* remove all interfaces if we have a problem with bind */
1382 for (iface = interfaces; iface; iface = iface->i_next) {
1383 if (ifconfig( iface->i_name, SIOCDIFADDR, &iface->i_addr )) {
1384 #ifdef SIOCATALKDIFADDR
1385 #if (SIOCDIFADDR != SIOCATALKDIFADDR)
1386 ifconfig( iface->i_name, SIOCATALKDIFADDR, &iface->i_addr );
1387 #endif /* SIOCDIFADDR != SIOCATALKDIFADDR */
1388 #endif /* SIOCATALKDIFADDR */
1391 #endif /* SIOCDIFADDR */
1396 /* recalculate nfds and fds */
1398 for ( nfds = 0, iface = interfaces; iface; iface = iface->i_next ) {
1399 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1400 FD_SET( ap->ap_fd, &fds );
1401 if ( ap->ap_fd > nfds ) {
1409 int ifsetallmulti ( iname, set )
1416 memset(&ifr, 0, sizeof(ifr));
1418 if (( sock = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1422 /* get interface config */
1423 strlcpy(ifr.ifr_name, iname, sizeof(ifr.ifr_name));
1424 if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
1429 /* should we set or unset IFF_ALLMULTI */
1431 ifr.ifr_flags |= IFF_ALLMULTI;
1433 ifr.ifr_flags &= ~IFF_ALLMULTI;
1435 /* set interface config */
1436 strlcpy(ifr.ifr_name, iname, sizeof(ifr.ifr_name));
1437 if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) {
1446 int ifconfig( iname, cmd, sa )
1449 struct sockaddr_at *sa;
1454 memset(&ifr, 0, sizeof(ifr));
1455 strcpy( ifr.ifr_name, iname );
1456 ifr.ifr_addr = *(struct sockaddr *)sa;
1458 if (( s = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1461 if ( ioctl( s, cmd, &ifr ) < 0 ) {
1466 if ( cmd == SIOCGIFADDR ) {
1467 *(struct sockaddr *)sa = ifr.ifr_addr;
1472 void dumpconfig( iface )
1473 struct interface *iface;
1477 printf( "%s", iface->i_name );
1478 if ( iface->i_flags & IFACE_RSEED ) {
1479 printf( " -router" );
1480 } else if ( iface->i_flags & IFACE_SEED ) {
1484 if ( iface->i_flags & IFACE_DONTROUTE)
1485 printf( " -dontroute");
1487 printf( " -phase" );
1488 if ( iface->i_flags & IFACE_PHASE1 ) {
1493 printf( " -net %d", ntohs( iface->i_rt->rt_firstnet ));
1494 if ( iface->i_rt->rt_lastnet != iface->i_rt->rt_firstnet ) {
1495 printf( "-%d", ntohs( iface->i_rt->rt_lastnet ));
1497 printf( " -addr %u.%u", ntohs( iface->i_addr.sat_addr.s_net ),
1498 iface->i_addr.sat_addr.s_node );
1499 printf( " -caddr %u.%u", ntohs( iface->i_caddr.sat_addr.s_net ),
1500 iface->i_caddr.sat_addr.s_node );
1501 for ( l = iface->i_rt->rt_zt; l; l = l->l_next ) {
1502 printf( " -zone %.*s", ((struct ziptab *)l->l_data)->zt_len,
1503 ((struct ziptab *)l->l_data)->zt_name );
1511 struct interface *iface;
1512 struct rtmptab *rtmp;
1516 for ( iface = interfaces; iface; iface = iface->i_next ) {
1517 for ( rtmp = iface->i_rt; rtmp; rtmp = rtmp->rt_inext ) {
1518 if ( rtmp->rt_gate == 0 ) {
1519 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
1520 printf( "%u-%u", ntohs( rtmp->rt_firstnet ),
1521 ntohs( rtmp->rt_lastnet ));
1523 printf( "%u", ntohs( rtmp->rt_firstnet ));
1526 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
1527 printf( "%u.%u for %u-%u",
1528 ntohs( rtmp->rt_gate->g_sat.sat_addr.s_net ),
1529 rtmp->rt_gate->g_sat.sat_addr.s_node,
1530 ntohs( rtmp->rt_firstnet ),
1531 ntohs( rtmp->rt_lastnet ));
1533 printf( "%u.%u for %u",
1534 ntohs( rtmp->rt_gate->g_sat.sat_addr.s_net ),
1535 rtmp->rt_gate->g_sat.sat_addr.s_node,
1536 ntohs( rtmp->rt_firstnet ));
1540 if ( rtmp->rt_iprev == 0 && rtmp != iface->i_rt ) {
1544 for ( l = rtmp->rt_zt; l; l = l->l_next ) {
1545 zt = (struct ziptab *)l->l_data;
1546 printf( " %.*s", zt->zt_len, zt->zt_name );
1559 struct interface *iface;
1560 struct rtmptab *rtmp;
1564 for ( zt = ziptab; zt; zt = zt->zt_next ) {
1565 printf( "%.*s", zt->zt_len, zt->zt_name );
1566 for ( l = zt->zt_rt; l; l = l->l_next ) {
1567 rtmp = (struct rtmptab *)l->l_data;
1568 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
1569 printf( " %u-%u", ntohs( rtmp->rt_firstnet ),
1570 ntohs( rtmp->rt_lastnet ));
1572 printf( " %u", ntohs( rtmp->rt_firstnet ));
1574 if ( rtmp->rt_iprev == 0 && rtmp->rt_gate != 0 ) {