2 * $Id: main.c,v 1.24 2009-12-13 01:17:16 didg Exp $
4 * Copyright (c) 1990,1993 Regents of The University of Michigan.
5 * All Rights Reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
12 #include <sys/param.h>
13 #include <sys/socket.h>
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/nbp.h>
59 #include <atalk/ddp.h>
60 #include <atalk/atp.h>
61 #include <atalk/paths.h>
62 #include <atalk/util.h>
65 #include <sys/sockio.h>
69 #include "interface.h"
78 /* Forward Declarations */
79 int ifconfig(const char *iname, unsigned long cmd, struct sockaddr_at *sa);
81 /* FIXME/SOCKLEN_T: socklen_t is a unix98 feature */
83 #define SOCKLEN_T unsigned int
84 #endif /* SOCKLEN_T */
87 #define WEXITSTATUS(x) ((x).w_retcode)
88 #endif /* WEXITSTATUS */
90 /* linux has a special ioctl for appletalk device destruction. as of
91 * 2.1.57, SIOCDIFADDR works w/ linux. okay, we need to deal with the
92 * fact that SIOCDIFADDR may be defined on linux despite the fact that
94 #if !defined(SIOCDIFADDR) && defined(SIOCATALKDIFADDR)
95 #define SIOCDIFADDR SIOCATALKDIFADDR
98 #define elements(a) (sizeof(a)/sizeof((a)[0]))
102 extern int aep_packet(struct atport *ap, struct sockaddr_at *from, char *data, int len);
106 int stabletimer, newrtmpdata = 0;
108 static struct atserv atserv[] = {
109 { "rtmp", 1, rtmp_packet }, /* 0 */
110 { "nbp", 2, nbp_packet }, /* 1 */
111 { "echo", 4, aep_packet }, /* 2 */
112 { "zip", 6, zip_packet }, /* 3 */
114 static int atservNATSERV = elements( atserv );
116 struct interface *interfaces = NULL, *ciface = NULL;
118 static int debug = 0, quiet = 0, chatty = 0;
119 static char *configfile = NULL;
120 static int ziptimeout = 0;
121 static int stable = 0, noparent = 0;
122 static int ninterfaces;
123 static int defphase = IFACE_PHASE2;
126 static char Packet[ PKTSZ ];
127 static char *version = VERSION;
128 static char *pidfile = _PATH_ATALKDLOCK;
133 int readconf( char * );
134 int getifconf( void );
135 int writeconf( char * );
137 /* this is the messiest of the bunch as atalkd can exit pretty much
138 * everywhere. we delete interfaces here instead of in as_down. */
139 static void atalkd_exit(const int i)
142 struct interface *iface;
144 for (iface = interfaces; iface; iface = iface->i_next) {
145 if (ifconfig( iface->i_name, SIOCDIFADDR, &iface->i_addr)) {
146 #ifdef SIOCATALKDIFADDR
147 #if (SIOCDIFADDR != SIOCATALKDIFADDR)
148 if (!ifconfig(iface->i_name, SIOCATALKDIFADDR, &iface->i_addr))
150 #endif /* SIOCDIFADDR != SIOCATALKDIFADDR */
151 #endif /* SIOCATALKIFADDR */
152 LOG(log_error, logtype_atalkd, "difaddr(%u.%u): %s",
153 ntohs(iface->i_addr.sat_addr.s_net),
154 iface->i_addr.sat_addr.s_node, strerror(errno));
157 if (!(iface->i_flags & IFACE_WASALLMULTI) && (iface->i_flags & IFACE_ALLMULTI))
158 ifsetallmulti(iface->i_name, 0);
161 #endif /* SOPCDOFADDR */
163 server_unlock(pidfile);
168 static void as_timer(int sig _U_)
170 struct sockaddr_at sat;
173 struct rtmp_tuple rt;
174 struct atport *ap, *zap, *rap;
175 struct interface *iface, *iface2;
176 struct gate *gate, *fgate = NULL;
177 struct rtmptab *rtmp, *frtmp;
179 char *data, *end, packet[ ATP_BUFSIZ ];
185 memset(&sat, 0, sizeof( struct sockaddr_at ));
186 for ( iface = interfaces; iface; iface = iface->i_next ) {
187 if ( iface->i_flags & IFACE_LOOPBACK ) {
190 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
191 if ( ap->ap_packet == zip_packet ) {
194 if ( ap->ap_packet == rtmp_packet ) {
199 if (( iface->i_flags & ( IFACE_ADDR|IFACE_CONFIG|IFACE_NOROUTER )) == IFACE_ADDR ) {
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, "as_timer multiple interfaces, no seed" );
224 LOG(log_info, logtype_atalkd, "as_timer can't configure %s", iface->i_name );
225 LOG(log_info, logtype_atalkd, "as_timer waiting for router" );
230 * Complete configuration for iface, and boot next
233 iface->i_flags |= IFACE_CONFIG;
234 for ( zt = iface->i_czt; zt; zt = zt->zt_next ) {
235 if (addzone( iface->i_rt, zt->zt_len, zt->zt_name) < 0) {
236 LOG(log_error, logtype_atalkd, "addzone: %s", strerror(errno));
240 if ( iface->i_rt->rt_zt ) {
241 iface->i_rt->rt_flags &= ~RTMPTAB_ZIPQUERY;
242 iface->i_rt->rt_flags |= RTMPTAB_HASZONES;
244 if ( iface->i_flags & IFACE_PHASE1 ) {
245 LOG(log_info, logtype_atalkd, "as_timer configured %s phase 1 from seed", iface->i_name );
246 setaddr( iface, IFACE_PHASE1,
247 iface->i_caddr.sat_addr.s_net,
248 iface->i_addr.sat_addr.s_node,
249 iface->i_caddr.sat_addr.s_net,
250 iface->i_caddr.sat_addr.s_net );
252 LOG(log_info, logtype_atalkd, "as_timer configured %s phase 2 from seed", iface->i_name );
255 if ( looproute( iface, RTMP_ADD )) { /* -1 or 1 */
256 LOG(log_error, logtype_atalkd, "as_timer: can't route %u.%u to loop: %s",
257 ntohs( iface->i_addr.sat_addr.s_net ),
258 iface->i_addr.sat_addr.s_node, strerror(errno) );
261 if ( iface == ciface ) {
262 ciface = ciface->i_next;
268 * Configure for no router operation. Wait for a route
269 * to become available in rtmp_packet().
271 LOG(log_info, logtype_atalkd, "config for no router" );
273 if ( iface->i_flags & IFACE_PHASE2 ) {
274 iface->i_rt->rt_firstnet = 0;
275 iface->i_rt->rt_lastnet = htons( STARTUP_LASTNET );
276 setaddr( iface, IFACE_PHASE2, iface->i_addr.sat_addr.s_net, iface->i_addr.sat_addr.s_node,
277 0, htons( STARTUP_LASTNET ));
279 if ( looproute( iface, RTMP_ADD ) ) { /* -1 or 1 */
280 LOG(log_error, logtype_atalkd, "as_timer: can't route %u.%u to loopback: %s",
281 ntohs( iface->i_addr.sat_addr.s_net ), iface->i_addr.sat_addr.s_node,
286 if ( iface == ciface ) {
287 ciface = ciface->i_next;
294 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
296 free( (caddr_t)fgate );
301 data = packet + 1 + sizeof( struct ziphdr );
302 end = packet + sizeof( packet );
305 sat.sat_port = zap->ap_port;
308 * Perform timeouts on routers. If we've only got one
309 * interface, we'll use these timeouts to decide that
310 * our zone has gone away.
312 if ( ++gate->g_state >= RTMPTAB_BAD ) {
313 LOG(log_info, logtype_atalkd, "as_timer gateway %u.%u down", ntohs( gate->g_sat.sat_addr.s_net ),
314 gate->g_sat.sat_addr.s_node );
317 frtmp = rtmp->rt_next;
318 if ( rtmp->rt_hops == RTMPHOPS_POISON || rtmp->rt_iprev == NULL ) {
321 rtmp->rt_hops = RTMPHOPS_POISON;
322 if ((cc = rtmp_replace( rtmp )) < 0) {
323 LOG(log_error, logtype_atalkd, "rtmp_replace: %s", strerror(errno));
327 gate->g_state = rtmp->rt_state = RTMPTAB_GOOD;
332 if ( gate->g_rt == NULL ) {
333 if ( gate->g_prev == NULL ) {
334 gate->g_iface->i_gate = gate->g_next;
336 gate->g_prev->g_next = gate->g_next;
338 if ( gate->g_next != NULL ) {
339 gate->g_next->g_prev = gate->g_prev;
341 fgate = gate; /* can't free here, just mark it */
344 * If this is the last router on the only interface,
345 * reconfigure our netrange. By marking the interface
346 * as having no router, we will notice when a router
349 * XXX: actually, we always reconfigure an interface
350 * if we're not a seed router.
353 if ( gate->g_iface->i_gate == NULL && ((iface->i_flags & IFACE_SEED) == 0)) {
354 gate->g_iface->i_flags |= IFACE_NOROUTER;
355 gate->g_iface->i_flags &= ~IFACE_CONFIG;
357 /* get rid of any zones associated with this iface */
358 if (gate->g_iface->i_rt->rt_zt) {
359 rtmp_delzonemap(gate->g_iface->i_rt);
360 gate->g_iface->i_rt->rt_flags &= ~RTMPTAB_HASZONES;
363 LOG(log_info, logtype_atalkd, "as_timer last gateway down" );
365 /* Set netrange to 0-fffe. */
366 if ( gate->g_iface->i_flags & IFACE_PHASE2 ) {
367 gate->g_iface->i_rt->rt_firstnet = 0;
368 gate->g_iface->i_rt->rt_lastnet =
369 htons( STARTUP_LASTNET );
370 setaddr( iface, IFACE_PHASE2,
371 iface->i_addr.sat_addr.s_net,
372 iface->i_addr.sat_addr.s_node,
373 0, htons( STARTUP_LASTNET ));
380 * If we don't have a zone for our interface yet, ask for
381 * it from any router (all routers) on the interface.
383 if (( iface->i_rt->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
384 iface->i_rt->rt_flags |= RTMPTAB_ZIPQUERY;
385 memcpy( data, &iface->i_rt->rt_firstnet, sizeof( u_short ));
386 data += sizeof( u_short );
393 * Delete old routing tuples.
395 if ( rtmp->rt_state != RTMPTAB_PERM ) {
400 * We've not been updated for this route in a while. If
401 * it's not in use, go ahead and remove it. If it is in
402 * use, mark the route as down (POISON), and look for a
403 * better route. If one is found, delete this route and use
404 * the new one. If it's not found, mark the route as GOOD
405 * (so we'll propogate our poison) and delete it the next
406 * time it becomes BAD.
408 if ( rtmp->rt_state >= RTMPTAB_BAD ) {
409 frtmp = rtmp->rt_next;
410 if ( rtmp->rt_iprev == NULL ) { /* not in use */
412 } else { /* in use */
413 if ( rtmp->rt_hops == RTMPHOPS_POISON ) {
416 rtmp->rt_hops = RTMPHOPS_POISON;
417 if ((cc = rtmp_replace( rtmp )) < 0) {
418 LOG(log_error, logtype_atalkd, "rtmp_replace: %s", strerror(errno));
422 rtmp->rt_state = RTMPTAB_GOOD;
432 if ( rtmp->rt_iprev && ( rtmp->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
433 if ( data + sizeof( u_short ) > end || n == 255 ) {
434 /* send what we've got */
435 zh.zh_op = ZIPOP_QUERY;
439 *data++ = DDPTYPE_ZIP;
440 memcpy( data, &zh, sizeof( struct ziphdr ));
442 if ( sendto( zap->ap_fd, packet, cc, 0,
443 (struct sockaddr *)&sat,
444 sizeof( struct sockaddr_at )) < 0 ) {
445 LOG(log_error, logtype_atalkd, "as_timer sendto: %s", strerror(errno) );
450 data = packet + 1 + sizeof( struct ziphdr );
451 end = packet + sizeof( packet );
455 * rt_nzq is number of ZIP Queries we've issued for a
456 * given netrange. If we've got ziptimeout on, we
457 * will only ask 3 times for any given netrange.
458 * Interestingly enough, since rt_nzq is a u_char,
459 * it will overflow after a while. This means we will
460 * periodically ask for nets that we've decided not to
461 * ask about, and warn that we can't get it's zone.
463 if ( rtmp->rt_nzq++ == 3 ) {
464 LOG(log_info, logtype_atalkd, "as_timer can't get zone for %u", ntohs( rtmp->rt_firstnet ));
466 if ( rtmp->rt_nzq > 3 ) {
468 rtmp = rtmp->rt_next;
474 rtmp->rt_flags |= RTMPTAB_ZIPQUERY;
475 memcpy( data, &rtmp->rt_firstnet, sizeof( u_short ));
476 data += sizeof( u_short );
479 rtmp = rtmp->rt_next;
482 /* send what we've got */
484 zh.zh_op = ZIPOP_QUERY;
488 *data++ = DDPTYPE_ZIP;
489 memcpy( data, &zh, sizeof( struct ziphdr ));
491 if ( sendto( zap->ap_fd, packet, cc, 0, (struct sockaddr *)&sat, sizeof( struct sockaddr_at )) < 0 ) {
492 LOG(log_error, logtype_atalkd, "as_timer sendto: %s", strerror(errno) );
497 free( (caddr_t)fgate );
502 * Send RTMP broadcasts if we have multiple interfaces or our
503 * interface is configured as a router.
505 if ((iface->i_flags & IFACE_ISROUTER)) {
507 sat.sat_len = sizeof( struct sockaddr_at );
509 sat.sat_family = AF_APPLETALK;
510 sat.sat_addr.s_net = ATADDR_ANYNET;
511 sat.sat_addr.s_node = ATADDR_BCAST;
512 sat.sat_port = rap->ap_port;
515 end = data + sizeof( packet );
516 *data++ = DDPTYPE_RTMPRD;
517 rh.rh_net = iface->i_addr.sat_addr.s_net;
519 rh.rh_node = iface->i_addr.sat_addr.s_node;
520 memcpy( data, &rh, sizeof( struct rtmp_head ));
521 data += sizeof( struct rtmp_head );
525 if ( iface->i_flags & IFACE_PHASE1 ) {
528 memcpy( data, &rt, SZ_RTMPTUPLE );
529 data += SZ_RTMPTUPLE;
531 rt.rt_net = iface->i_rt->rt_firstnet;
533 memcpy( data, &rt, SZ_RTMPTUPLE );
534 data += SZ_RTMPTUPLE;
536 rt.rt_net = iface->i_rt->rt_lastnet;
538 memcpy( data, &rt, SZ_RTMPTUPLE );
539 data += SZ_RTMPTUPLE;
542 for ( iface2 = interfaces; iface2; iface2 = iface2->i_next ) {
544 /* XXX: there used to be a bit checking against iface ==
545 iface2. also, we don't want to send an rtmp broadcast
546 to an interface that doesn't want it. */
547 if ((( iface2->i_flags & IFACE_CONFIG ) == 0) ||
548 ((iface2->i_flags & IFACE_ISROUTER) == 0)) {
552 * Fill in tuples. Always send the same thing, regardless
553 * of the phase of the destination. Routers who don't
554 * understand extended rtmp packets will toss extended
555 * tuples because their distance will have the high bit set.
557 for ( rtmp = iface2->i_rt; rtmp; rtmp = rtmp->rt_inext ) {
558 /* don't broadcast routes we have no zone for */
559 if ( rtmp->rt_zt == NULL ||
560 ( rtmp->rt_flags & RTMPTAB_ZIPQUERY ) ||
561 ( rtmp->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
566 if (rtmp->rt_iface == iface) {
570 if ((( rtmp->rt_flags & RTMPTAB_EXTENDED ) &&
571 data + 2 * SZ_RTMPTUPLE > end ) ||
572 data + SZ_RTMPTUPLE > end ) {
573 if ( sendto( rap->ap_fd, packet, data - packet, 0,
574 (struct sockaddr *)&sat,
575 sizeof( struct sockaddr_at )) < 0 ) {
576 LOG(log_error, logtype_atalkd, "as_timer sendto %u.%u (%u): %s",
577 ntohs( sat.sat_addr.s_net ),
579 ntohs( iface->i_rt->rt_firstnet ),
583 if ( iface->i_flags & IFACE_PHASE2 ) {
584 data = packet + 1 + sizeof( struct rtmp_head ) + 2 * SZ_RTMPTUPLE;
586 data = packet + 1 + sizeof( struct rtmp_head ) + SZ_RTMPTUPLE;
591 rt.rt_net = rtmp->rt_firstnet;
592 rt.rt_dist = rtmp->rt_hops;
593 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
596 memcpy( data, &rt, SZ_RTMPTUPLE );
597 data += SZ_RTMPTUPLE;
599 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
600 rt.rt_net = rtmp->rt_lastnet;
602 memcpy( data, &rt, SZ_RTMPTUPLE );
603 data += SZ_RTMPTUPLE;
611 if ( sendto( rap->ap_fd, packet, data - packet, 0, (struct sockaddr *)&sat,
612 sizeof( struct sockaddr_at )) < 0 ) {
613 LOG(log_error, logtype_atalkd, "as_timer sendto %u.%u (%u): %s",
614 ntohs( sat.sat_addr.s_net ),
616 ntohs( iface->i_rt->rt_firstnet ),
624 * Check if we're stable. Each time we configure an interface, we
625 * sent stabletimer to UNSTABLE. If stabletimer ever gets to
626 * STABLEANYWAY, we give up and decide to "be" stable anyway.
627 * Normally, we wait for stabletimer get <= STABLE with no new rtmp
628 * data and all zip data complete.
631 if ( stabletimer <= STABLE && !newrtmpdata && !sentzipq ) {
632 /* write out config file */
634 writeconf( configfile );
636 if ( stabletimer-- <= STABLEANYWAY ) {
642 if ( stable && !noparent ) {
644 LOG(log_info, logtype_atalkd, "ready %d/%d/%d", stabletimer, newrtmpdata,
648 * Seems like we could get here more than once...
650 if ( kill( getpid(), SIGSTOP ) < 0 ) {
651 LOG(log_error, logtype_atalkd, "as_timer: kill-self failed!" );
665 * Consistency check...
669 struct rtmptab *rtmp;
670 struct list *lr, *lz;
673 for ( zt = ziptab; zt; zt = zt->zt_next ) {
674 for ( lr = zt->zt_rt; lr; lr = lr->l_next ) {
675 rtmp = (struct rtmptab *)lr->l_data;
676 if ( rtmp->rt_iprev == 0 && rtmp->rt_gate != 0 ) {
677 LOG(log_error, logtype_atalkd, "%.*s has %u-%u (unused)",
678 zt->zt_len, zt->zt_name, ntohs( rtmp->rt_firstnet ),
679 ntohs( rtmp->rt_lastnet ));
682 for ( lz = rtmp->rt_zt; lz; lz = lz->l_next ) {
683 if ( zt == (struct ziptab *)lz->l_data ) {
688 LOG(log_error, logtype_atalkd, "no map from %u-%u to %.*s",
689 ntohs( rtmp->rt_firstnet ),
690 ntohs( rtmp->rt_lastnet ),
691 zt->zt_len, zt->zt_name );
700 as_debug(int sig _U_)
702 struct interface *iface;
709 if (( rtmpdebug = fopen( _PATH_ATALKDEBUG, "w" )) == NULL ) {
710 LOG(log_error, logtype_atalkd, "rtmp: %s", strerror(errno) );
713 for ( iface = interfaces; iface; iface = iface->i_next ) {
714 fprintf( rtmpdebug, "interface %s %u.%u ", iface->i_name,
715 ntohs( iface->i_addr.sat_addr.s_net ),
716 iface->i_addr.sat_addr.s_node );
717 if ( iface->i_flags & IFACE_PHASE1 ) {
718 putc( '1', rtmpdebug );
720 if ( iface->i_flags & IFACE_PHASE2 ) {
721 putc( '2', rtmpdebug );
723 if ( iface->i_flags & IFACE_RSEED ) {
724 putc( 'R', rtmpdebug );
726 if ( iface->i_flags & IFACE_SEED ) {
727 putc( 'S', rtmpdebug );
729 if ( iface->i_flags & IFACE_DONTROUTE ) {
730 putc( 'D', rtmpdebug );
732 if ( iface->i_flags & IFACE_ADDR ) {
733 putc( 'A', rtmpdebug );
735 if ( iface->i_flags & IFACE_CONFIG ) {
736 putc( 'C', rtmpdebug );
738 if ( iface->i_flags & IFACE_NOROUTER ) {
739 putc( 'N', rtmpdebug );
741 if ( iface->i_flags & IFACE_LOOP ) {
742 putc( 'L', rtmpdebug );
744 putc( '\n', rtmpdebug );
747 fprintf( rtmpdebug, "\t%u-%u ",
748 ntohs( iface->i_rt->rt_firstnet ),
749 ntohs( iface->i_rt->rt_lastnet ));
750 if ( iface->i_rt->rt_flags & RTMPTAB_ZIPQUERY ) {
751 putc( 'q', rtmpdebug );
753 if ( iface->i_rt->rt_flags & RTMPTAB_HASZONES ) {
754 putc( 'z', rtmpdebug );
756 if ( iface->i_rt->rt_flags & RTMPTAB_EXTENDED ) {
757 putc( 'x', rtmpdebug );
759 putc( 'i', rtmpdebug );
760 for ( l = iface->i_rt->rt_zt; l; l = l->l_next ) {
761 zt = (struct ziptab *)l->l_data;
762 fprintf( rtmpdebug, " '%.*s'", zt->zt_len, zt->zt_name );
764 fprintf( rtmpdebug, "\n" );
767 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
768 fprintf( rtmpdebug, "gate %u.%u %X\n",
769 ntohs( gate->g_sat.sat_addr.s_net ),
770 gate->g_sat.sat_addr.s_node, gate->g_state );
771 for ( rt = gate->g_rt; rt; rt = rt->rt_next ) {
772 fprintf( rtmpdebug, "\t%u-%u ", ntohs( rt->rt_firstnet ),
773 ntohs( rt->rt_lastnet ));
774 if ( rt->rt_flags & RTMPTAB_ZIPQUERY ) {
775 putc( 'q', rtmpdebug );
777 if ( rt->rt_flags & RTMPTAB_HASZONES ) {
778 putc( 'z', rtmpdebug );
780 if ( rt->rt_flags & RTMPTAB_EXTENDED ) {
781 putc( 'x', rtmpdebug );
783 if ( rt->rt_iprev ) {
784 putc( 'i', rtmpdebug );
786 for ( l = rt->rt_zt; l; l = l->l_next ) {
787 zt = (struct ziptab *)l->l_data;
788 fprintf( rtmpdebug, " '%.*s'", zt->zt_len, zt->zt_name );
790 fprintf( rtmpdebug, "\n" );
799 * Called when SIGTERM is recieved. Remove all routes and then exit.
804 struct interface *iface;
808 for ( iface = interfaces; iface; iface = iface->i_next ) {
809 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
810 for ( rt = gate->g_rt; rt; rt = rt->rt_next ) {
811 if ( rt->rt_iprev ) {
812 if ( gateroute( RTMP_DEL, rt ) < 0 ) {
813 LOG(log_error, logtype_atalkd, "as_down remove %u-%u failed: %s",
814 ntohs( rt->rt_firstnet ),
815 ntohs( rt->rt_lastnet ),
821 if ( iface->i_flags & IFACE_LOOP ) {
822 if (looproute( iface, RTMP_DEL )) {
823 LOG(log_error, logtype_atalkd, "as_down remove %s %u.%u failed: %s",
824 iface->i_name, ntohs( iface->i_addr.sat_addr.s_net ),
825 iface->i_addr.sat_addr.s_node,
831 LOG(log_info, logtype_atalkd, "done" );
835 int main( int ac, char **av)
840 struct sockaddr_at sat;
843 sigset_t signal_set, old_set;
845 struct interface *iface;
853 while (( c = getopt( ac, av, "12qsdtf:P:v" )) != EOF ) {
856 defphase = IFACE_PHASE1;
860 defphase = IFACE_PHASE2;
871 case 'q' : /* don't seed */
875 case 's' : /* seed */
879 case 't' : /* transition */
883 case 'P' : /* pid file */
887 case 'v' : /* version */
888 printf( "atalkd (version %s)\n", version );
893 fprintf( stderr, "Unknown option -- '%c'\n", c );
897 if ( optind != ac ) {
898 fprintf( stderr, "Too many arguments.\n" );
902 if (( prog = strrchr( av[ 0 ], '/' )) == NULL ) {
909 * Configure loop back address first, so appearances of "lo0" in
910 * the config file fail. Also insures that lo0 gets configured,
911 * even if there's some hangup during configuration of some
914 if (( interfaces = newiface( LOOPIFACE )) == NULL ) {
915 perror( "newiface" );
918 interfaces->i_flags |= IFACE_PHASE2 | IFACE_LOOPBACK;
921 * Check our initial configuration before we fork. This way we can
922 * complain about syntax errors on stdout.
924 * Basically, if we're going to read our config file, we should read
925 * it and initialize our data structures. If we're not going to read
926 * our config file, use GIFCONF to initialize our data structures.
928 if ( readconf( configfile ) < 0 && getifconf() < 0 ) {
929 fprintf( stderr, "%s: can't get interfaces, exiting.\n", prog );
933 /* we need to count up our interfaces so that we can simplify things
934 * later. we also need to figure out if we have more than one interface
935 * that is routing. */
936 for (i = 0, ninterfaces = 0, iface = interfaces; iface;
937 iface=iface->i_next) {
938 if (iface->i_flags & IFACE_DONTROUTE)
942 i = ninterfaces - i; /* number of routable interfaces */
945 * At this point, we have (at least partially) initialized data
946 * structures. Fill in what we can and verify that nothing is obviously
949 for (iface = interfaces; iface; iface = iface->i_next) {
950 /* Apply the default phase */
951 if (( iface->i_flags & IFACE_PHASE1 ) == 0 &&
952 ( iface->i_flags & IFACE_PHASE2 ) == 0 ) {
953 iface->i_flags |= defphase;
956 /* set up router flag information. if we have multiple interfaces
957 * and DONTROUTE isn't set, set up ROUTER. i is the number of
958 * interfaces that don't have the DONTROUTE flag set. */
959 if ((i > IFBASE) && ((iface->i_flags & IFACE_DONTROUTE) == 0)) {
960 iface->i_flags |= IFACE_ISROUTER;
963 /* Set default addresses */
964 if ( iface->i_rt == NULL ) {
965 if (( iface->i_rt = newrt(iface)) == NULL ) {
970 if ( iface->i_flags & IFACE_PHASE1 ) {
971 iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet =
972 iface->i_caddr.sat_addr.s_net;
974 if ( iface->i_caddr.sat_addr.s_net != ATADDR_ANYNET ||
975 ( iface->i_flags & IFACE_LOOPBACK )) {
976 iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet =
977 iface->i_caddr.sat_addr.s_net;
979 iface->i_rt->rt_firstnet = htons( STARTUP_FIRSTNET );
980 iface->i_rt->rt_lastnet = htons( STARTUP_LASTNET );
985 if (( iface->i_flags & IFACE_PHASE1 ) == 0 ) {
986 iface->i_rt->rt_flags |= RTMPTAB_EXTENDED;
989 if ( iface->i_caddr.sat_addr.s_net == ATADDR_ANYNET ) {
990 iface->i_caddr.sat_addr.s_net = iface->i_rt->rt_firstnet;
994 dumpconfig( iface ); /* probably needs args */
999 * A little consistency check...
1001 if ( ninterfaces < IFBASE ) {
1002 fprintf( stderr, "%s: zero interfaces, exiting.\n", prog );
1007 * Set process name for logging
1010 set_processname("atalkd");
1012 /* do this here so that we can use ifconfig */
1014 if ( plumb() < 0 ) {
1015 fprintf(stderr, "can't establish STREAMS plumbing, exiting.\n" );
1018 #endif /* __svr4__ */
1020 /* delete pre-existing interface addresses. */
1022 for (iface = interfaces; iface; iface = iface->i_next) {
1023 if (ifconfig(iface->i_name, SIOCDIFADDR, &iface->i_addr)) {
1024 #ifdef SIOCATALKDIFADDR
1025 #if (SIOCDIFADDR != SIOCATALKDIFADDR)
1026 ifconfig(iface->i_name, SIOCATALKDIFADDR, &iface->i_addr);
1027 #endif /* SIOCDIFADDR != SIOCATALKDIFADDR */
1028 #endif /* SIOCATALKDIFADDR */
1031 #endif /* SIOCDIFADDR */
1034 * Disassociate. The child will send itself a signal when it is
1035 * stable. This indicates that other processes may begin using
1038 switch (i = server_lock("atalkd", pidfile, debug)) {
1043 default: /* parent */
1045 * Wait for the child to send itself a SIGSTOP, after which
1046 * we send it a SIGCONT and exit ourself.
1048 if ( wait3( &status, WUNTRACED, (struct rusage *)0 ) != i) {
1049 perror( "wait3" ); /* Child died? */
1052 if ( !WIFSTOPPED( status )) {
1053 fprintf( stderr, "AppleTalk not up! Check your syslog for the reason." );
1054 if ( WIFEXITED( status )) {
1055 fprintf( stderr, " Child exited with %d.\n",
1056 WEXITSTATUS( status ));
1058 fprintf( stderr, " Child died.\n" );
1062 if ( kill(i, SIGCONT ) < 0 ) {
1070 openlog( prog, LOG_PID );
1072 set_processname(prog);
1073 syslog_setup(log_debug, logtype_default, logoption_pid, logfacility_daemon );
1076 LOG(log_info, logtype_atalkd, "restart (%s)", version );
1079 * Socket for use in routing ioctl()s. Can't add routes to our
1080 * interfaces until we have our routing socket.
1083 if (( rtfd = socket( PF_ROUTE, SOCK_RAW, AF_APPLETALK )) < 0 ) {
1084 LOG(log_error, logtype_atalkd, "route socket: %s", strerror(errno) );
1087 if ( shutdown( rtfd, 0 ) < 0 ) {
1088 LOG(log_error, logtype_atalkd, "route shutdown: %s", strerror(errno) );
1092 if (( rtfd = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1093 LOG(log_error, logtype_atalkd, "route socket: %s", strerror(errno) );
1098 ciface = interfaces;
1101 memset(&sv, 0, sizeof(sv));
1102 sv.sa_handler = as_down;
1103 sigemptyset( &sv.sa_mask );
1104 sigaddset( &sv.sa_mask, SIGUSR1 );
1105 sigaddset( &sv.sa_mask, SIGALRM );
1106 sigaddset( &sv.sa_mask, SIGTERM );
1107 sv.sa_flags = SA_RESTART;
1108 if ( sigaction( SIGTERM, &sv, NULL) < 0 ) {
1109 LOG(log_error, logtype_atalkd, "sigterm: %s", strerror(errno) );
1113 sv.sa_handler = as_debug;
1114 sigemptyset( &sv.sa_mask );
1115 sigaddset( &sv.sa_mask, SIGUSR1 );
1116 sigaddset( &sv.sa_mask, SIGALRM );
1117 sigaddset( &sv.sa_mask, SIGTERM );
1118 sv.sa_flags = SA_RESTART;
1119 if ( sigaction( SIGUSR1, &sv, NULL) < 0 ) {
1120 LOG(log_error, logtype_atalkd, "sigusr1: %s", strerror(errno) );
1124 sv.sa_handler = as_timer;
1125 sigemptyset( &sv.sa_mask );
1126 sigaddset( &sv.sa_mask, SIGUSR1 );
1127 sigaddset( &sv.sa_mask, SIGALRM );
1128 sigaddset( &sv.sa_mask, SIGTERM );
1129 sv.sa_flags = SA_RESTART;
1130 if ( sigaction( SIGALRM, &sv, NULL) < 0 ) {
1131 LOG(log_error, logtype_atalkd, "sigalrm: %s", strerror(errno) );
1135 it.it_interval.tv_sec = 10L;
1136 it.it_interval.tv_usec = 0L;
1137 it.it_value.tv_sec = 10L;
1138 it.it_value.tv_usec = 0L;
1139 if ( setitimer( ITIMER_REAL, &it, NULL) < 0 ) {
1140 LOG(log_error, logtype_atalkd, "setitimer: %s", strerror(errno) );
1144 sigemptyset( &signal_set );
1145 sigaddset(&signal_set, SIGALRM);
1147 /* don't block SIGTERM */
1148 sigaddset(&signal_set, SIGTERM);
1150 sigaddset(&signal_set, SIGUSR1);
1154 if ( select( nfds, &readfds, NULL, NULL, NULL) < 0 ) {
1155 if ( errno == EINTR ) {
1159 LOG(log_error, logtype_atalkd, "select: %s", strerror(errno) );
1164 for ( iface = interfaces; iface; iface = iface->i_next ) {
1165 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1166 if ( FD_ISSET( ap->ap_fd, &readfds )) {
1167 if ( ap->ap_packet ) {
1168 fromlen = sizeof( struct sockaddr_at );
1169 if (( c = recvfrom( ap->ap_fd, Packet, sizeof( Packet ),
1170 0, (struct sockaddr *)&sat, &fromlen )) < 0 ) {
1171 LOG(log_error, logtype_atalkd, "recvfrom: %s", strerror(errno) );
1176 printf( "packet from %u.%u on %s (%x) %d (%d)\n",
1177 ntohs( sat.sat_addr.s_net ),
1178 sat.sat_addr.s_node, iface->i_name,
1179 iface->i_flags, ap->ap_port, ap->ap_fd );
1180 bprint( Packet, c );
1183 if (sigprocmask(SIG_BLOCK, &signal_set, &old_set) < 0) {
1184 LOG(log_error, logtype_atalkd, "sigprocmask: %s", strerror(errno) );
1188 if (( *ap->ap_packet )( ap, &sat, Packet, c ) < 0) {
1189 LOG(log_error, logtype_atalkd, "ap->ap_packet: %s", strerror(errno));
1196 if (sigprocmask(SIG_SETMASK, &old_set, NULL) < 0) {
1197 LOG(log_error, logtype_atalkd, "sigprocmask old set: %s", strerror(errno) );
1209 * This code is called (from main(), as_timer(), zip_packet(),
1210 * and rtmp_packet()) to set the initial "bootstrapping" address
1213 void bootaddr(struct interface *iface)
1215 if ( iface == NULL ) {
1220 if ( iface->i_flags & IFACE_ADDR ) {
1221 LOG(log_error, logtype_atalkd, "bootaddr OOPS!" );
1225 if ( iface->i_flags & IFACE_PHASE1 ) {
1226 setaddr( iface, IFACE_PHASE1, 0,
1227 iface->i_caddr.sat_addr.s_node, 0, 0 );
1229 if ( iface->i_flags & IFACE_LOOPBACK ) {
1230 iface->i_flags |= IFACE_CONFIG | IFACE_ADDR;
1231 if ( ciface == iface ) {
1232 ciface = ciface->i_next;
1236 } else if (rtmp_request( iface ) < 0) {
1237 LOG(log_error, logtype_atalkd, "bootaddr (rtmp_request): %s", strerror(errno));
1242 setaddr( iface, IFACE_PHASE2, iface->i_caddr.sat_addr.s_net,
1243 iface->i_caddr.sat_addr.s_node,
1244 iface->i_rt->rt_firstnet, iface->i_rt->rt_lastnet );
1246 if ( iface->i_flags & IFACE_LOOPBACK ) {
1247 iface->i_flags |= IFACE_CONFIG | IFACE_ADDR;
1248 if ( ciface == iface ) {
1249 ciface = ciface->i_next;
1253 } else if (zip_getnetinfo( iface ) < 0) {
1254 LOG(log_error, logtype_atalkd, "bootaddr (zip_getnetinfo): %s", strerror(errno));
1259 iface->i_flags |= IFACE_ADDR;
1260 stabletimer = UNSTABLE;
1266 * to manage the i_ports field and the fds for select().
1268 void setaddr(struct interface *iface,
1269 u_int8_t phase, u_int16_t net, u_int8_t node,
1270 u_int16_t first, u_int16_t last)
1276 struct sockaddr_at sat;
1279 if ( iface->i_ports == NULL ) { /* allocate port structures */
1280 for ( i = 0, as = atserv; i < atservNATSERV; i++, as++ ) {
1281 if (( se = getservbyname( as->as_name, "ddp" )) == NULL ) {
1282 LOG(log_info, logtype_atalkd, "%s: service unknown", as->as_name );
1284 as->as_port = ntohs( se->s_port );
1286 if (( ap = (struct atport *)malloc( sizeof( struct atport ))) ==
1288 LOG(log_error, logtype_atalkd, "malloc: %s", strerror(errno) );
1292 ap->ap_next = iface->i_ports;
1293 ap->ap_iface = iface;
1294 ap->ap_port = as->as_port;
1295 ap->ap_packet = as->as_packet;
1297 iface->i_ports = ap;
1299 } else { /* close ports */
1300 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1301 (void)close( ap->ap_fd );
1306 iface->i_addr.sat_len = sizeof( struct sockaddr_at );
1308 iface->i_addr.sat_family = AF_APPLETALK;
1309 iface->i_addr.sat_addr.s_net = net;
1310 iface->i_addr.sat_addr.s_node = node;
1312 nr.nr_phase = phase;
1313 nr.nr_firstnet = first;
1314 nr.nr_lastnet = last;
1315 memcpy( iface->i_addr.sat_zero, &nr, sizeof( struct netrange ));
1317 if ( ifconfig( iface->i_name, SIOCSIFADDR, &iface->i_addr )) {
1318 LOG(log_error, logtype_atalkd, "setifaddr: %s (%u-%u): %s. try specifying a \
1319 smaller net range.", iface->i_name, ntohs(first), ntohs(last), strerror(errno));
1322 if ( ifconfig( iface->i_name, SIOCGIFADDR, &iface->i_addr )) {
1323 LOG(log_error, logtype_atalkd, "getifaddr: %s: %s", iface->i_name, strerror(errno) );
1328 i = 1; /* enable broadcasts */
1330 /* useless message, no? */
1331 LOG(log_info, logtype_atalkd, "setsockopt incompatible w/ Solaris STREAMS module.");
1332 #endif /* __svr4__ */
1333 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1334 if (( ap->ap_fd = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1335 LOG(log_error, logtype_atalkd, "socket: %s", strerror(errno) );
1339 setsockopt(ap->ap_fd, SOL_SOCKET, SO_BROADCAST, &i, sizeof(i));
1340 #endif /* ! __svr4 */
1342 memset( &sat, 0, sizeof( struct sockaddr_at ));
1344 sat.sat_len = sizeof( struct sockaddr_at );
1346 sat.sat_family = AF_APPLETALK;
1347 sat.sat_addr.s_net = iface->i_addr.sat_addr.s_net;
1348 sat.sat_addr.s_node = iface->i_addr.sat_addr.s_node;
1349 sat.sat_port = ap->ap_port;
1351 if ( bind( ap->ap_fd, (struct sockaddr *)&sat,
1352 sizeof( struct sockaddr_at )) < 0 ) {
1353 LOG(log_error, logtype_atalkd, "bind %u.%u:%u: %s",
1354 ntohs( sat.sat_addr.s_net ),
1355 sat.sat_addr.s_node, sat.sat_port, strerror(errno) );
1357 /* remove all interfaces if we have a problem with bind */
1358 for (iface = interfaces; iface; iface = iface->i_next) {
1359 if (ifconfig( iface->i_name, SIOCDIFADDR, &iface->i_addr )) {
1360 #ifdef SIOCATALKDIFADDR
1361 #if (SIOCDIFADDR != SIOCATALKDIFADDR)
1362 ifconfig( iface->i_name, SIOCATALKDIFADDR, &iface->i_addr );
1363 #endif /* SIOCDIFADDR != SIOCATALKDIFADDR */
1364 #endif /* SIOCATALKDIFADDR */
1367 #endif /* SIOCDIFADDR */
1372 /* recalculate nfds and fds */
1374 for ( nfds = 0, iface = interfaces; iface; iface = iface->i_next ) {
1375 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1376 FD_SET( ap->ap_fd, &fds );
1377 if ( ap->ap_fd > nfds ) {
1385 int ifsetallmulti (const char *iname, int set)
1390 memset(&ifr, 0, sizeof(ifr));
1392 if (( sock = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1396 /* get interface config */
1397 strlcpy(ifr.ifr_name, iname, sizeof(ifr.ifr_name));
1398 if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
1403 /* should we set or unset IFF_ALLMULTI */
1405 ifr.ifr_flags |= IFF_ALLMULTI;
1407 ifr.ifr_flags &= ~IFF_ALLMULTI;
1409 /* set interface config */
1410 strlcpy(ifr.ifr_name, iname, sizeof(ifr.ifr_name));
1411 if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) {
1420 int ifconfig( const char *iname, unsigned long cmd, struct sockaddr_at *sa)
1425 memset(&ifr, 0, sizeof(ifr));
1426 strcpy( ifr.ifr_name, iname );
1427 ifr.ifr_addr = *(struct sockaddr *)sa;
1429 if (( s = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1432 if ( ioctl( s, cmd, &ifr ) < 0 ) {
1437 if ( cmd == SIOCGIFADDR ) {
1438 *(struct sockaddr *)sa = ifr.ifr_addr;
1443 void dumpconfig( struct interface *iface)
1447 printf( "%s", iface->i_name );
1448 if ( iface->i_flags & IFACE_RSEED ) {
1449 printf( " -router" );
1450 } else if ( iface->i_flags & IFACE_SEED ) {
1454 if ( iface->i_flags & IFACE_DONTROUTE)
1455 printf( " -dontroute");
1457 printf( " -phase" );
1458 if ( iface->i_flags & IFACE_PHASE1 ) {
1463 printf( " -net %d", ntohs( iface->i_rt->rt_firstnet ));
1464 if ( iface->i_rt->rt_lastnet != iface->i_rt->rt_firstnet ) {
1465 printf( "-%d", ntohs( iface->i_rt->rt_lastnet ));
1467 printf( " -addr %u.%u", ntohs( iface->i_addr.sat_addr.s_net ),
1468 iface->i_addr.sat_addr.s_node );
1469 printf( " -caddr %u.%u", ntohs( iface->i_caddr.sat_addr.s_net ),
1470 iface->i_caddr.sat_addr.s_node );
1471 for ( l = iface->i_rt->rt_zt; l; l = l->l_next ) {
1472 printf( " -zone %.*s", ((struct ziptab *)l->l_data)->zt_len,
1473 ((struct ziptab *)l->l_data)->zt_name );
1479 void dumproutes(void)
1481 struct interface *iface;
1482 struct rtmptab *rtmp;
1486 for ( iface = interfaces; iface; iface = iface->i_next ) {
1487 for ( rtmp = iface->i_rt; rtmp; rtmp = rtmp->rt_inext ) {
1488 if ( rtmp->rt_gate == 0 ) {
1489 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
1490 printf( "%u-%u", ntohs( rtmp->rt_firstnet ),
1491 ntohs( rtmp->rt_lastnet ));
1493 printf( "%u", ntohs( rtmp->rt_firstnet ));
1496 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
1497 printf( "%u.%u for %u-%u",
1498 ntohs( rtmp->rt_gate->g_sat.sat_addr.s_net ),
1499 rtmp->rt_gate->g_sat.sat_addr.s_node,
1500 ntohs( rtmp->rt_firstnet ),
1501 ntohs( rtmp->rt_lastnet ));
1503 printf( "%u.%u for %u",
1504 ntohs( rtmp->rt_gate->g_sat.sat_addr.s_net ),
1505 rtmp->rt_gate->g_sat.sat_addr.s_node,
1506 ntohs( rtmp->rt_firstnet ));
1510 if ( rtmp->rt_iprev == 0 && rtmp != iface->i_rt ) {
1514 for ( l = rtmp->rt_zt; l; l = l->l_next ) {
1515 zt = (struct ziptab *)l->l_data;
1516 printf( " %.*s", zt->zt_len, zt->zt_name );
1527 void dumpzones(void)
1529 struct interface *iface;
1530 struct rtmptab *rtmp;
1534 for ( zt = ziptab; zt; zt = zt->zt_next ) {
1535 printf( "%.*s", zt->zt_len, zt->zt_name );
1536 for ( l = zt->zt_rt; l; l = l->l_next ) {
1537 rtmp = (struct rtmptab *)l->l_data;
1538 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
1539 printf( " %u-%u", ntohs( rtmp->rt_firstnet ),
1540 ntohs( rtmp->rt_lastnet ));
1542 printf( " %u", ntohs( rtmp->rt_firstnet ));
1544 if ( rtmp->rt_iprev == 0 && rtmp->rt_gate != 0 ) {