2 * $Id: main.c,v 1.17.8.6.2.1 2005-01-31 17:01:04 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>
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 */
35 #define WIFSTOPPED(status) (((status) & 0xff) == 0x7f)
41 #include <net/route.h>
44 #include <net/route.h>
46 #include <netinet/in.h>
49 #include <atalk/logger.h>
57 #include <netatalk/endian.h>
58 #include <netatalk/at.h>
59 #include <atalk/compat.h>
60 #include <atalk/zip.h>
61 #include <atalk/rtmp.h>
62 #include <atalk/ddp.h>
63 #include <atalk/atp.h>
64 #include <atalk/paths.h>
65 #include <atalk/util.h>
68 #include <sys/sockio.h>
72 #include "interface.h"
80 /* Forward Declarations */
81 int ifconfig(const char *iname, unsigned long cmd, struct sockaddr_at *sa);
83 /* FIXME/SOCKLEN_T: socklen_t is a unix98 feature */
85 #define SOCKLEN_T unsigned int
86 #endif /* SOCKLEN_T */
89 #define WEXITSTATUS(x) ((x).w_retcode)
90 #endif /* WEXITSTATUS */
92 /* linux has a special ioctl for appletalk device destruction. as of
93 * 2.1.57, SIOCDIFADDR works w/ linux. okay, we need to deal with the
94 * fact that SIOCDIFADDR may be defined on linux despite the fact that
96 #if !defined(SIOCDIFADDR) && defined(SIOCATALKDIFADDR)
97 #define SIOCDIFADDR SIOCATALKDIFADDR
100 #define elements(a) (sizeof(a)/sizeof((a)[0]))
104 extern int rtmp_packet();
105 extern int nbp_packet();
106 extern int aep_packet();
107 extern int zip_packet();
111 struct atserv atserv[] = {
112 { "rtmp", 1, rtmp_packet }, /* 0 */
113 { "nbp", 2, nbp_packet }, /* 1 */
114 { "echo", 4, aep_packet }, /* 2 */
115 { "zip", 6, zip_packet }, /* 3 */
117 int atservNATSERV = elements( atserv );
119 struct interface *interfaces = NULL, *ciface = NULL;
121 int debug = 0, quiet = 0, chatty = 0;
122 char *configfile = NULL;
123 int ziptimeout = 0, transition = 0;
124 int stabletimer, stable = 0, newrtmpdata = 0, noparent = 0;
125 static int ninterfaces;
126 int defphase = IFACE_PHASE2;
129 char Packet[ PKTSZ ];
130 char *version = VERSION;
131 static char *pidfile = _PATH_ATALKDLOCK;
136 int readconf( char * );
137 int getifconf( void );
138 int writeconf( char * );
140 /* this is the messiest of the bunch as atalkd can exit pretty much
141 * everywhere. we delete interfaces here instead of in as_down. */
142 static void atalkd_exit(const int i)
145 struct interface *iface;
147 for (iface = interfaces; iface; iface = iface->i_next) {
148 if (ifconfig( iface->i_name, SIOCDIFADDR, &iface->i_addr)) {
149 #ifdef SIOCATALKDIFADDR
150 #if (SIOCDIFADDR != SIOCATALKDIFADDR)
151 if (!ifconfig(iface->i_name, SIOCATALKDIFADDR, &iface->i_addr))
153 #endif /* SIOCDIFADDR != SIOCATALKDIFADDR */
154 #endif /* SIOCATALKIFADDR */
155 LOG(log_error, logtype_atalkd, "difaddr(%u.%u): %s",
156 ntohs(iface->i_addr.sat_addr.s_net),
157 iface->i_addr.sat_addr.s_node, strerror(errno));
160 if (!(iface->i_flags & IFACE_WASALLMULTI) && (iface->i_flags & IFACE_ALLMULTI))
161 ifsetallmulti(iface->i_name, 0);
164 #endif /* SOPCDOFADDR */
166 server_unlock(pidfile);
171 static void as_timer(int sig)
173 struct sockaddr_at sat;
176 struct rtmp_tuple rt;
177 struct atport *ap, *zap, *rap;
178 struct interface *iface, *iface2;
179 struct gate *gate, *fgate = NULL;
180 struct rtmptab *rtmp, *frtmp;
182 char *data, *end, packet[ ATP_BUFSIZ ];
188 memset(&sat, 0, sizeof( struct sockaddr_at ));
189 for ( iface = interfaces; iface; iface = iface->i_next ) {
190 if ( iface->i_flags & IFACE_LOOPBACK ) {
193 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
194 if ( ap->ap_packet == zip_packet ) {
197 if ( ap->ap_packet == rtmp_packet ) {
202 if (( iface->i_flags & ( IFACE_ADDR|IFACE_CONFIG|IFACE_NOROUTER )) ==
204 if ( iface->i_time < 3 ) {
205 if ( iface->i_flags & IFACE_PHASE1 ) {
206 if (rtmp_request( iface ) < 0) {
207 LOG(log_error, logtype_atalkd, "rtmp_request: %s", strerror(errno));
212 if (zip_getnetinfo( iface ) < 0) {
213 LOG(log_error, logtype_atalkd, "zip_getnetinfo: %s", strerror(errno));
220 iface->i_flags |= IFACE_NOROUTER;
221 if ((iface->i_flags & IFACE_ISROUTER)) {
222 if (( iface->i_flags & IFACE_SEED ) == 0 ) {
224 * No seed info, and we've got multiple interfaces.
227 LOG(log_info, logtype_atalkd,
228 "as_timer multiple interfaces, no seed" );
229 LOG(log_info, logtype_atalkd, "as_timer can't configure %s",
231 LOG(log_info, logtype_atalkd, "as_timer waiting for router" );
236 * Complete configuration for iface, and boot next
239 iface->i_flags |= IFACE_CONFIG;
240 for ( zt = iface->i_czt; zt; zt = zt->zt_next ) {
241 if (addzone( iface->i_rt, zt->zt_len,
243 LOG(log_error, logtype_atalkd, "addzone: %s", strerror(errno));
247 if ( iface->i_rt->rt_zt ) {
248 iface->i_rt->rt_flags &= ~RTMPTAB_ZIPQUERY;
249 iface->i_rt->rt_flags |= RTMPTAB_HASZONES;
251 if ( iface->i_flags & IFACE_PHASE1 ) {
252 LOG(log_info, logtype_atalkd,
253 "as_timer configured %s phase 1 from seed",
255 setaddr( iface, IFACE_PHASE1,
256 iface->i_caddr.sat_addr.s_net,
257 iface->i_addr.sat_addr.s_node,
258 iface->i_caddr.sat_addr.s_net,
259 iface->i_caddr.sat_addr.s_net );
261 LOG(log_info, logtype_atalkd,
262 "as_timer configured %s phase 2 from seed",
266 if ( looproute( iface, RTMP_ADD )) { /* -1 or 1 */
267 LOG(log_error, logtype_atalkd,
268 "as_timer: can't route %u.%u to loop: %s",
269 ntohs( iface->i_addr.sat_addr.s_net ),
270 iface->i_addr.sat_addr.s_node,
274 if ( iface == ciface ) {
275 ciface = ciface->i_next;
281 * Configure for no router operation. Wait for a route
282 * to become available in rtmp_packet().
284 LOG(log_info, logtype_atalkd, "config for no router" );
286 if ( iface->i_flags & IFACE_PHASE2 ) {
287 iface->i_rt->rt_firstnet = 0;
288 iface->i_rt->rt_lastnet = htons( STARTUP_LASTNET );
289 setaddr( iface, IFACE_PHASE2,
290 iface->i_addr.sat_addr.s_net,
291 iface->i_addr.sat_addr.s_node,
292 0, htons( STARTUP_LASTNET ));
294 if ( looproute( iface, RTMP_ADD ) ) { /* -1 or 1 */
295 LOG(log_error, logtype_atalkd,
296 "as_timer: can't route %u.%u to loopback: %s",
297 ntohs( iface->i_addr.sat_addr.s_net ),
298 iface->i_addr.sat_addr.s_node,
303 if ( iface == ciface ) {
304 ciface = ciface->i_next;
311 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
313 free( (caddr_t)fgate );
318 data = packet + 1 + sizeof( struct ziphdr );
319 end = packet + sizeof( packet );
322 sat.sat_port = zap->ap_port;
325 * Perform timeouts on routers. If we've only got one
326 * interface, we'll use these timeouts to decide that
327 * our zone has gone away.
329 if ( ++gate->g_state >= RTMPTAB_BAD ) {
330 LOG(log_info, logtype_atalkd, "as_timer gateway %u.%u down",
331 ntohs( gate->g_sat.sat_addr.s_net ),
332 gate->g_sat.sat_addr.s_node );
335 frtmp = rtmp->rt_next;
336 if ( rtmp->rt_hops == RTMPHOPS_POISON ||
337 rtmp->rt_iprev == 0 ) {
340 rtmp->rt_hops = RTMPHOPS_POISON;
341 if ((cc = rtmp_replace( rtmp )) < 0) {
342 LOG(log_error, logtype_atalkd, "rtmp_replace: %s", strerror(errno));
346 gate->g_state = rtmp->rt_state = RTMPTAB_GOOD;
351 if ( gate->g_rt == 0 ) {
352 if ( gate->g_prev == 0 ) {
353 gate->g_iface->i_gate = gate->g_next;
355 gate->g_prev->g_next = gate->g_next;
357 if ( gate->g_next != 0 ) {
358 gate->g_next->g_prev = gate->g_prev;
360 fgate = gate; /* can't free here, just mark it */
363 * If this is the last router on the only interface,
364 * reconfigure our netrange. By marking the interface
365 * as having no router, we will notice when a router
368 * XXX: actually, we always reconfigure an interface
369 * if we're not a seed router.
372 if ( gate->g_iface->i_gate == 0 &&
373 ((iface->i_flags & IFACE_SEED) == 0)) {
374 gate->g_iface->i_flags |= IFACE_NOROUTER;
375 gate->g_iface->i_flags &= ~IFACE_CONFIG;
377 /* get rid of any zones associated with this iface */
378 if (gate->g_iface->i_rt->rt_zt) {
379 rtmp_delzonemap(gate->g_iface->i_rt);
380 gate->g_iface->i_rt->rt_flags &= ~RTMPTAB_HASZONES;
383 LOG(log_info, logtype_atalkd, "as_timer last gateway down" );
385 /* Set netrange to 0-fffe. */
386 if ( gate->g_iface->i_flags & IFACE_PHASE2 ) {
387 gate->g_iface->i_rt->rt_firstnet = 0;
388 gate->g_iface->i_rt->rt_lastnet =
389 htons( STARTUP_LASTNET );
390 setaddr( iface, IFACE_PHASE2,
391 iface->i_addr.sat_addr.s_net,
392 iface->i_addr.sat_addr.s_node,
393 0, htons( STARTUP_LASTNET ));
400 * If we don't have a zone for our interface yet, ask for
401 * it from any router (all routers) on the interface.
403 if (( iface->i_rt->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
404 iface->i_rt->rt_flags |= RTMPTAB_ZIPQUERY;
405 memcpy( data, &iface->i_rt->rt_firstnet, sizeof( u_short ));
406 data += sizeof( u_short );
413 * Delete old routing tuples.
415 if ( rtmp->rt_state != RTMPTAB_PERM ) {
420 * We've not been updated for this route in a while. If
421 * it's not in use, go ahead and remove it. If it is in
422 * use, mark the route as down (POISON), and look for a
423 * better route. If one is found, delete this route and use
424 * the new one. If it's not found, mark the route as GOOD
425 * (so we'll propogate our poison) and delete it the next
426 * time it becomes BAD.
428 if ( rtmp->rt_state >= RTMPTAB_BAD ) {
429 frtmp = rtmp->rt_next;
430 if ( rtmp->rt_iprev == 0 ) { /* not in use */
432 } else { /* in use */
433 if ( rtmp->rt_hops == RTMPHOPS_POISON ) {
436 rtmp->rt_hops = RTMPHOPS_POISON;
437 if ((cc = rtmp_replace( rtmp )) < 0) {
438 LOG(log_error, logtype_atalkd, "rtmp_replace: %s", strerror(errno));
442 rtmp->rt_state = RTMPTAB_GOOD;
452 if ( rtmp->rt_iprev &&
453 ( rtmp->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
454 if ( data + sizeof( u_short ) > end || n == 255 ) {
455 /* send what we've got */
456 zh.zh_op = ZIPOP_QUERY;
460 *data++ = DDPTYPE_ZIP;
461 memcpy( data, &zh, sizeof( struct ziphdr ));
463 if ( sendto( zap->ap_fd, packet, cc, 0,
464 (struct sockaddr *)&sat,
465 sizeof( struct sockaddr_at )) < 0 ) {
466 LOG(log_error, logtype_atalkd, "as_timer sendto: %s", strerror(errno) );
471 data = packet + 1 + sizeof( struct ziphdr );
472 end = packet + sizeof( packet );
476 * rt_nzq is number of ZIP Queries we've issued for a
477 * given netrange. If we've got ziptimeout on, we
478 * will only ask 3 times for any given netrange.
479 * Interestingly enough, since rt_nzq is a u_char,
480 * it will overflow after a while. This means we will
481 * periodically ask for nets that we've decided not to
482 * ask about, and warn that we can't get it's zone.
484 if ( rtmp->rt_nzq++ == 3 ) {
485 LOG(log_info, logtype_atalkd, "as_timer can't get zone for %u",
486 ntohs( rtmp->rt_firstnet ));
488 if ( rtmp->rt_nzq > 3 ) {
490 rtmp = rtmp->rt_next;
496 rtmp->rt_flags |= RTMPTAB_ZIPQUERY;
497 memcpy( data, &rtmp->rt_firstnet, sizeof( u_short ));
498 data += sizeof( u_short );
501 rtmp = rtmp->rt_next;
504 /* send what we've got */
506 zh.zh_op = ZIPOP_QUERY;
510 *data++ = DDPTYPE_ZIP;
511 memcpy( data, &zh, sizeof( struct ziphdr ));
513 if ( sendto( zap->ap_fd, packet, cc, 0, (struct sockaddr *)&sat,
514 sizeof( struct sockaddr_at )) < 0 ) {
515 LOG(log_error, logtype_atalkd, "as_timer sendto: %s", strerror(errno) );
520 free( (caddr_t)fgate );
525 * Send RTMP broadcasts if we have multiple interfaces or our
526 * interface is configured as a router.
528 if ((iface->i_flags & IFACE_ISROUTER)) {
530 sat.sat_len = sizeof( struct sockaddr_at );
532 sat.sat_family = AF_APPLETALK;
533 sat.sat_addr.s_net = ATADDR_ANYNET;
534 sat.sat_addr.s_node = ATADDR_BCAST;
535 sat.sat_port = rap->ap_port;
538 end = data + sizeof( packet );
539 *data++ = DDPTYPE_RTMPRD;
540 rh.rh_net = iface->i_addr.sat_addr.s_net;
542 rh.rh_node = iface->i_addr.sat_addr.s_node;
543 memcpy( data, &rh, sizeof( struct rtmp_head ));
544 data += sizeof( struct rtmp_head );
548 if ( iface->i_flags & IFACE_PHASE1 ) {
551 memcpy( data, &rt, SZ_RTMPTUPLE );
552 data += SZ_RTMPTUPLE;
554 rt.rt_net = iface->i_rt->rt_firstnet;
556 memcpy( data, &rt, SZ_RTMPTUPLE );
557 data += SZ_RTMPTUPLE;
559 rt.rt_net = iface->i_rt->rt_lastnet;
561 memcpy( data, &rt, SZ_RTMPTUPLE );
562 data += SZ_RTMPTUPLE;
565 for ( iface2 = interfaces; iface2; iface2 = iface2->i_next ) {
567 /* XXX: there used to be a bit checking against iface ==
568 iface2. also, we don't want to send an rtmp broadcast
569 to an interface that doesn't want it. */
570 if ((( iface2->i_flags & IFACE_CONFIG ) == 0) ||
571 ((iface2->i_flags & IFACE_ISROUTER) == 0)) {
575 * Fill in tuples. Always send the same thing, regardless
576 * of the phase of the destination. Routers who don't
577 * understand extended rtmp packets will toss extended
578 * tuples because their distance will have the high bit set.
580 for ( rtmp = iface2->i_rt; rtmp; rtmp = rtmp->rt_inext ) {
581 /* don't broadcast routes we have no zone for */
582 if ( rtmp->rt_zt == 0 ||
583 ( rtmp->rt_flags & RTMPTAB_ZIPQUERY ) ||
584 ( rtmp->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
588 if ((( rtmp->rt_flags & RTMPTAB_EXTENDED ) &&
589 data + 2 * SZ_RTMPTUPLE > end ) ||
590 data + SZ_RTMPTUPLE > end ) {
591 if ( sendto( rap->ap_fd, packet, data - packet, 0,
592 (struct sockaddr *)&sat,
593 sizeof( struct sockaddr_at )) < 0 ) {
594 LOG(log_error, logtype_atalkd, "as_timer sendto %u.%u (%u): %s",
595 ntohs( sat.sat_addr.s_net ),
597 ntohs( iface->i_rt->rt_firstnet ),
601 if ( iface->i_flags & IFACE_PHASE2 ) {
602 data = packet + 1 + sizeof( struct rtmp_head ) +
605 data = packet + 1 + sizeof( struct rtmp_head ) +
611 rt.rt_net = rtmp->rt_firstnet;
612 rt.rt_dist = rtmp->rt_hops;
613 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
616 memcpy( data, &rt, SZ_RTMPTUPLE );
617 data += SZ_RTMPTUPLE;
619 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
620 rt.rt_net = rtmp->rt_lastnet;
622 memcpy( data, &rt, SZ_RTMPTUPLE );
623 data += SZ_RTMPTUPLE;
631 if ( sendto( rap->ap_fd, packet, data - packet, 0,
632 (struct sockaddr *)&sat,
633 sizeof( struct sockaddr_at )) < 0 ) {
634 LOG(log_error, logtype_atalkd, "as_timer sendto %u.%u (%u): %s",
635 ntohs( sat.sat_addr.s_net ),
637 ntohs( iface->i_rt->rt_firstnet ),
645 * Check if we're stable. Each time we configure an interface, we
646 * sent stabletimer to UNSTABLE. If stabletimer ever gets to
647 * STABLEANYWAY, we give up and decide to "be" stable anyway.
648 * Normally, we wait for stabletimer get <= STABLE with no new rtmp
649 * data and all zip data complete.
652 if ( stabletimer <= STABLE && !newrtmpdata && !sentzipq ) {
653 /* write out config file */
655 writeconf( configfile );
657 if ( stabletimer-- <= STABLEANYWAY ) {
663 if ( stable && !noparent ) {
665 LOG(log_info, logtype_atalkd, "ready %d/%d/%d", stabletimer, newrtmpdata,
669 * Seems like we could get here more than once...
671 if ( kill( getpid(), SIGSTOP ) < 0 ) {
672 LOG(log_error, logtype_atalkd, "as_timer: kill-self failed!" );
686 * Consistency check...
690 struct rtmptab *rtmp;
691 struct list *lr, *lz;
694 for ( zt = ziptab; zt; zt = zt->zt_next ) {
695 for ( lr = zt->zt_rt; lr; lr = lr->l_next ) {
696 rtmp = (struct rtmptab *)lr->l_data;
697 if ( rtmp->rt_iprev == 0 && rtmp->rt_gate != 0 ) {
698 LOG(log_error, logtype_atalkd, "%.*s has %u-%u (unused)",
699 zt->zt_len, zt->zt_name, ntohs( rtmp->rt_firstnet ),
700 ntohs( rtmp->rt_lastnet ));
703 for ( lz = rtmp->rt_zt; lz; lz = lz->l_next ) {
704 if ( zt == (struct ziptab *)lz->l_data ) {
709 LOG(log_error, logtype_atalkd, "no map from %u-%u to %.*s",
710 ntohs( rtmp->rt_firstnet ),
711 ntohs( rtmp->rt_lastnet ),
712 zt->zt_len, zt->zt_name );
720 #if !defined( ibm032 ) && !defined( _IBMR2 )
722 #endif /* ! ibm032 && ! _IBMR2 */
725 struct interface *iface;
732 if (( rtmpdebug = fopen( _PATH_ATALKDEBUG, "w" )) == NULL ) {
733 LOG(log_error, logtype_atalkd, "rtmp: %s", strerror(errno) );
736 for ( iface = interfaces; iface; iface = iface->i_next ) {
737 fprintf( rtmpdebug, "interface %s %u.%u ", iface->i_name,
738 ntohs( iface->i_addr.sat_addr.s_net ),
739 iface->i_addr.sat_addr.s_node );
740 if ( iface->i_flags & IFACE_PHASE1 ) {
741 putc( '1', rtmpdebug );
743 if ( iface->i_flags & IFACE_PHASE2 ) {
744 putc( '2', rtmpdebug );
746 if ( iface->i_flags & IFACE_RSEED ) {
747 putc( 'R', rtmpdebug );
749 if ( iface->i_flags & IFACE_SEED ) {
750 putc( 'S', rtmpdebug );
752 if ( iface->i_flags & IFACE_DONTROUTE ) {
753 putc( 'D', rtmpdebug );
755 if ( iface->i_flags & IFACE_ADDR ) {
756 putc( 'A', rtmpdebug );
758 if ( iface->i_flags & IFACE_CONFIG ) {
759 putc( 'C', rtmpdebug );
761 if ( iface->i_flags & IFACE_NOROUTER ) {
762 putc( 'N', rtmpdebug );
764 if ( iface->i_flags & IFACE_LOOP ) {
765 putc( 'L', rtmpdebug );
767 putc( '\n', rtmpdebug );
770 fprintf( rtmpdebug, "\t%u-%u ",
771 ntohs( iface->i_rt->rt_firstnet ),
772 ntohs( iface->i_rt->rt_lastnet ));
773 if ( iface->i_rt->rt_flags & RTMPTAB_ZIPQUERY ) {
774 putc( 'q', rtmpdebug );
776 if ( iface->i_rt->rt_flags & RTMPTAB_HASZONES ) {
777 putc( 'z', rtmpdebug );
779 if ( iface->i_rt->rt_flags & RTMPTAB_EXTENDED ) {
780 putc( 'x', rtmpdebug );
782 putc( 'i', rtmpdebug );
783 for ( l = iface->i_rt->rt_zt; l; l = l->l_next ) {
784 zt = (struct ziptab *)l->l_data;
785 fprintf( rtmpdebug, " '%.*s'", zt->zt_len, zt->zt_name );
787 fprintf( rtmpdebug, "\n" );
790 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
791 fprintf( rtmpdebug, "gate %u.%u %X\n",
792 ntohs( gate->g_sat.sat_addr.s_net ),
793 gate->g_sat.sat_addr.s_node, gate->g_state );
794 for ( rt = gate->g_rt; rt; rt = rt->rt_next ) {
795 fprintf( rtmpdebug, "\t%u-%u ", ntohs( rt->rt_firstnet ),
796 ntohs( rt->rt_lastnet ));
797 if ( rt->rt_flags & RTMPTAB_ZIPQUERY ) {
798 putc( 'q', rtmpdebug );
800 if ( rt->rt_flags & RTMPTAB_HASZONES ) {
801 putc( 'z', rtmpdebug );
803 if ( rt->rt_flags & RTMPTAB_EXTENDED ) {
804 putc( 'x', rtmpdebug );
806 if ( rt->rt_iprev ) {
807 putc( 'i', rtmpdebug );
809 for ( l = rt->rt_zt; l; l = l->l_next ) {
810 zt = (struct ziptab *)l->l_data;
811 fprintf( rtmpdebug, " '%.*s'", zt->zt_len, zt->zt_name );
813 fprintf( rtmpdebug, "\n" );
822 * Called when SIGTERM is recieved. Remove all routes and then exit.
824 #if !defined( ibm032 ) && !defined( _IBMR2 )
826 #endif /* ! ibm032 && ! _IBMR2 */
829 struct interface *iface;
833 for ( iface = interfaces; iface; iface = iface->i_next ) {
834 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
835 for ( rt = gate->g_rt; rt; rt = rt->rt_next ) {
836 if ( rt->rt_iprev ) {
837 if ( gateroute( RTMP_DEL, rt ) < 0 ) {
838 LOG(log_error, logtype_atalkd, "as_down remove %u-%u failed: %s",
839 ntohs( rt->rt_firstnet ),
840 ntohs( rt->rt_lastnet ),
846 if ( iface->i_flags & IFACE_LOOP ) {
847 if (looproute( iface, RTMP_DEL )) {
848 LOG(log_error, logtype_atalkd, "as_down remove %s %u.%u failed: %s",
849 iface->i_name, ntohs( iface->i_addr.sat_addr.s_net ),
850 iface->i_addr.sat_addr.s_node,
856 LOG(log_info, logtype_atalkd, "done" );
867 struct sockaddr_at sat;
870 sigset_t signal_set, old_set;
872 struct interface *iface;
880 while (( c = getopt( ac, av, "12qsdtf:P:v" )) != EOF ) {
883 defphase = IFACE_PHASE1;
887 defphase = IFACE_PHASE2;
898 case 'q' : /* don't seed */
902 case 's' : /* seed */
906 case 't' : /* transition */
910 case 'P' : /* pid file */
914 case 'v' : /* version */
915 printf( "atalkd (version %s)\n", version );
920 fprintf( stderr, "Unknown option -- '%c'\n", c );
924 if ( optind != ac ) {
925 fprintf( stderr, "Too many arguments.\n" );
929 if (( prog = strrchr( av[ 0 ], '/' )) == NULL ) {
936 * Configure loop back address first, so appearances of "lo0" in
937 * the config file fail. Also insures that lo0 gets configured,
938 * even if there's some hangup during configuration of some
941 if (( interfaces = newiface( LOOPIFACE )) == NULL ) {
942 perror( "newiface" );
945 interfaces->i_flags |= IFACE_PHASE2 | IFACE_LOOPBACK;
948 * Check our initial configuration before we fork. This way we can
949 * complain about syntax errors on stdout.
951 * Basically, if we're going to read our config file, we should read
952 * it and initialize our data structures. If we're not going to read
953 * our config file, use GIFCONF to initialize our data structures.
955 if ( readconf( configfile ) < 0 && getifconf() < 0 ) {
956 fprintf( stderr, "%s: can't get interfaces, exiting.\n", prog );
960 /* we need to count up our interfaces so that we can simplify things
961 * later. we also need to figure out if we have more than one interface
962 * that is routing. */
963 for (i = 0, ninterfaces = 0, iface = interfaces; iface;
964 iface=iface->i_next) {
965 if (iface->i_flags & IFACE_DONTROUTE)
969 i = ninterfaces - i; /* number of routable interfaces */
972 * At this point, we have (at least partially) initialized data
973 * structures. Fill in what we can and verify that nothing is obviously
976 for (iface = interfaces; iface; iface = iface->i_next) {
977 /* Apply the default phase */
978 if (( iface->i_flags & IFACE_PHASE1 ) == 0 &&
979 ( iface->i_flags & IFACE_PHASE2 ) == 0 ) {
980 iface->i_flags |= defphase;
983 /* set up router flag information. if we have multiple interfaces
984 * and DONTROUTE isn't set, set up ROUTER. i is the number of
985 * interfaces that don't have the DONTROUTE flag set. */
986 if ((i > IFBASE) && ((iface->i_flags & IFACE_DONTROUTE) == 0)) {
987 iface->i_flags |= IFACE_ISROUTER;
990 /* Set default addresses */
991 if ( iface->i_rt == NULL ) {
992 if (( iface->i_rt = newrt(iface)) == NULL ) {
997 if ( iface->i_flags & IFACE_PHASE1 ) {
998 iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet =
999 iface->i_caddr.sat_addr.s_net;
1001 if ( iface->i_caddr.sat_addr.s_net != ATADDR_ANYNET ||
1002 ( iface->i_flags & IFACE_LOOPBACK )) {
1003 iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet =
1004 iface->i_caddr.sat_addr.s_net;
1006 iface->i_rt->rt_firstnet = htons( STARTUP_FIRSTNET );
1007 iface->i_rt->rt_lastnet = htons( STARTUP_LASTNET );
1012 if (( iface->i_flags & IFACE_PHASE1 ) == 0 ) {
1013 iface->i_rt->rt_flags |= RTMPTAB_EXTENDED;
1016 if ( iface->i_caddr.sat_addr.s_net == ATADDR_ANYNET ) {
1017 iface->i_caddr.sat_addr.s_net = iface->i_rt->rt_firstnet;
1021 dumpconfig( iface ); /* probably needs args */
1026 * A little consistency check...
1028 if ( ninterfaces < IFBASE ) {
1029 fprintf( stderr, "%s: zero interfaces, exiting.\n", prog );
1034 * Set process name for logging
1037 set_processname("atalkd");
1039 /* do this here so that we can use ifconfig */
1041 if ( plumb() < 0 ) {
1042 fprintf(stderr, "can't establish STREAMS plumbing, exiting.\n" );
1045 #endif /* __svr4__ */
1047 /* delete pre-existing interface addresses. */
1049 for (iface = interfaces; iface; iface = iface->i_next) {
1050 if (ifconfig(iface->i_name, SIOCDIFADDR, &iface->i_addr)) {
1051 #ifdef SIOCATALKDIFADDR
1052 #if (SIOCDIFADDR != SIOCATALKDIFADDR)
1053 ifconfig(iface->i_name, SIOCATALKDIFADDR, &iface->i_addr);
1054 #endif /* SIOCDIFADDR != SIOCATALKDIFADDR */
1055 #endif /* SIOCATALKDIFADDR */
1058 #endif /* SIOCDIFADDR */
1061 * Disassociate. The child will send itself a signal when it is
1062 * stable. This indicates that other processes may begin using
1065 switch (i = server_lock("atalkd", pidfile, debug)) {
1070 default: /* parent */
1072 * Wait for the child to send itself a SIGSTOP, after which
1073 * we send it a SIGCONT and exit ourself.
1075 if ( wait3( &status, WUNTRACED, (struct rusage *)0 ) != i) {
1076 perror( "wait3" ); /* Child died? */
1079 if ( !WIFSTOPPED( status )) {
1080 fprintf( stderr, "AppleTalk not up! Check your syslog for the reason." );
1081 if ( WIFEXITED( status )) {
1082 fprintf( stderr, " Child exited with %d.\n",
1083 WEXITSTATUS( status ));
1085 fprintf( stderr, " Child died.\n" );
1089 if ( kill(i, SIGCONT ) < 0 ) {
1097 openlog( prog, LOG_PID );
1099 set_processname(prog);
1100 syslog_setup(log_debug, logtype_default, logoption_pid, logfacility_daemon );
1103 LOG(log_info, logtype_atalkd, "restart (%s)", version );
1106 * Socket for use in routing ioctl()s. Can't add routes to our
1107 * interfaces until we have our routing socket.
1110 if (( rtfd = socket( PF_ROUTE, SOCK_RAW, AF_APPLETALK )) < 0 ) {
1111 LOG(log_error, logtype_atalkd, "route socket: %s", strerror(errno) );
1114 if ( shutdown( rtfd, 0 ) < 0 ) {
1115 LOG(log_error, logtype_atalkd, "route shutdown: %s", strerror(errno) );
1119 if (( rtfd = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1120 LOG(log_error, logtype_atalkd, "route socket: %s", strerror(errno) );
1125 ciface = interfaces;
1128 memset(&sv, 0, sizeof(sv));
1129 sv.sa_handler = as_down;
1130 sigemptyset( &sv.sa_mask );
1131 sigaddset( &sv.sa_mask, SIGUSR1 );
1132 sigaddset( &sv.sa_mask, SIGALRM );
1133 sigaddset( &sv.sa_mask, SIGTERM );
1134 sv.sa_flags = SA_RESTART;
1135 if ( sigaction( SIGTERM, &sv, NULL) < 0 ) {
1136 LOG(log_error, logtype_atalkd, "sigterm: %s", strerror(errno) );
1140 sv.sa_handler = as_debug;
1141 sigemptyset( &sv.sa_mask );
1142 sigaddset( &sv.sa_mask, SIGUSR1 );
1143 sigaddset( &sv.sa_mask, SIGALRM );
1144 sigaddset( &sv.sa_mask, SIGTERM );
1145 sv.sa_flags = SA_RESTART;
1146 if ( sigaction( SIGUSR1, &sv, NULL) < 0 ) {
1147 LOG(log_error, logtype_atalkd, "sigusr1: %s", strerror(errno) );
1151 sv.sa_handler = as_timer;
1152 sigemptyset( &sv.sa_mask );
1153 sigaddset( &sv.sa_mask, SIGUSR1 );
1154 sigaddset( &sv.sa_mask, SIGALRM );
1155 sigaddset( &sv.sa_mask, SIGTERM );
1156 sv.sa_flags = SA_RESTART;
1157 if ( sigaction( SIGALRM, &sv, NULL) < 0 ) {
1158 LOG(log_error, logtype_atalkd, "sigalrm: %s", strerror(errno) );
1162 it.it_interval.tv_sec = 10L;
1163 it.it_interval.tv_usec = 0L;
1164 it.it_value.tv_sec = 10L;
1165 it.it_value.tv_usec = 0L;
1166 if ( setitimer( ITIMER_REAL, &it, NULL) < 0 ) {
1167 LOG(log_error, logtype_atalkd, "setitimer: %s", strerror(errno) );
1171 sigemptyset( &signal_set );
1172 sigaddset(&signal_set, SIGALRM);
1174 /* don't block SIGTERM */
1175 sigaddset(&signal_set, SIGTERM);
1177 sigaddset(&signal_set, SIGUSR1);
1181 if ( select( nfds, &readfds, NULL, NULL, NULL) < 0 ) {
1182 if ( errno == EINTR ) {
1186 LOG(log_error, logtype_atalkd, "select: %s", strerror(errno) );
1191 for ( iface = interfaces; iface; iface = iface->i_next ) {
1192 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1193 if ( FD_ISSET( ap->ap_fd, &readfds )) {
1194 if ( ap->ap_packet ) {
1195 fromlen = sizeof( struct sockaddr_at );
1196 if (( c = recvfrom( ap->ap_fd, Packet, sizeof( Packet ),
1197 0, (struct sockaddr *)&sat, &fromlen )) < 0 ) {
1198 LOG(log_error, logtype_atalkd, "recvfrom: %s", strerror(errno) );
1203 printf( "packet from %u.%u on %s (%x) %d (%d)\n",
1204 ntohs( sat.sat_addr.s_net ),
1205 sat.sat_addr.s_node, iface->i_name,
1206 iface->i_flags, ap->ap_port, ap->ap_fd );
1207 bprint( Packet, c );
1210 if (sigprocmask(SIG_BLOCK, &signal_set, &old_set) < 0) {
1211 LOG(log_error, logtype_atalkd, "sigprocmask: %s", strerror(errno) );
1215 if (( *ap->ap_packet )( ap, &sat, Packet, c ) < 0) {
1216 LOG(log_error, logtype_atalkd, "ap->ap_packet: %s", strerror(errno));
1223 if (sigprocmask(SIG_SETMASK, &old_set, NULL) < 0) {
1224 LOG(log_error, logtype_atalkd, "sigprocmask old set: %s", strerror(errno) );
1236 * This code is called (from main(), as_timer(), zip_packet(),
1237 * and rtmp_packet()) to set the initial "bootstrapping" address
1240 void bootaddr( iface )
1241 struct interface *iface;
1248 if ( iface->i_flags & IFACE_ADDR ) {
1249 LOG(log_error, logtype_atalkd, "bootaddr OOPS!" );
1253 if ( iface->i_flags & IFACE_PHASE1 ) {
1254 setaddr( iface, IFACE_PHASE1, 0,
1255 iface->i_caddr.sat_addr.s_node, 0, 0 );
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 (rtmp_request( iface ) < 0) {
1265 LOG(log_error, logtype_atalkd, "bootaddr (rtmp_request): %s", strerror(errno));
1270 setaddr( iface, IFACE_PHASE2, iface->i_caddr.sat_addr.s_net,
1271 iface->i_caddr.sat_addr.s_node,
1272 iface->i_rt->rt_firstnet, iface->i_rt->rt_lastnet );
1274 if ( iface->i_flags & IFACE_LOOPBACK ) {
1275 iface->i_flags |= IFACE_CONFIG | IFACE_ADDR;
1276 if ( ciface == iface ) {
1277 ciface = ciface->i_next;
1281 } else if (zip_getnetinfo( iface ) < 0) {
1282 LOG(log_error, logtype_atalkd, "bootaddr (zip_getnetinfo): %s", strerror(errno));
1287 iface->i_flags |= IFACE_ADDR;
1288 stabletimer = UNSTABLE;
1294 * to manage the i_ports field and the fds for select().
1296 void setaddr(struct interface *iface,
1297 u_int8_t phase, u_int16_t net, u_int8_t node,
1298 u_int16_t first, u_int16_t last)
1304 struct sockaddr_at sat;
1307 if ( iface->i_ports == NULL ) { /* allocate port structures */
1308 for ( i = 0, as = atserv; i < atservNATSERV; i++, as++ ) {
1309 if (( se = getservbyname( as->as_name, "ddp" )) == NULL ) {
1310 LOG(log_info, logtype_atalkd, "%s: service unknown", as->as_name );
1312 as->as_port = ntohs( se->s_port );
1314 if (( ap = (struct atport *)malloc( sizeof( struct atport ))) ==
1316 LOG(log_error, logtype_atalkd, "malloc: %s", strerror(errno) );
1320 ap->ap_next = iface->i_ports;
1321 ap->ap_iface = iface;
1322 ap->ap_port = as->as_port;
1323 ap->ap_packet = as->as_packet;
1325 iface->i_ports = ap;
1327 } else { /* close ports */
1328 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1329 (void)close( ap->ap_fd );
1334 iface->i_addr.sat_len = sizeof( struct sockaddr_at );
1336 iface->i_addr.sat_family = AF_APPLETALK;
1337 iface->i_addr.sat_addr.s_net = net;
1338 iface->i_addr.sat_addr.s_node = node;
1340 nr.nr_phase = phase;
1341 nr.nr_firstnet = first;
1342 nr.nr_lastnet = last;
1343 memcpy( iface->i_addr.sat_zero, &nr, sizeof( struct netrange ));
1345 if ( ifconfig( iface->i_name, SIOCSIFADDR, &iface->i_addr )) {
1346 LOG(log_error, logtype_atalkd, "setifaddr: %s (%u-%u): %s. try specifying a \
1347 smaller net range.", iface->i_name, ntohs(first), ntohs(last), strerror(errno));
1350 if ( ifconfig( iface->i_name, SIOCGIFADDR, &iface->i_addr )) {
1351 LOG(log_error, logtype_atalkd, "getifaddr: %s: %s", iface->i_name, strerror(errno) );
1356 i = 1; /* enable broadcasts */
1358 /* useless message, no? */
1359 LOG(log_info, logtype_atalkd, "setsockopt incompatible w/ Solaris STREAMS module.");
1360 #endif /* __svr4__ */
1361 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1362 if (( ap->ap_fd = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1363 LOG(log_error, logtype_atalkd, "socket: %s", strerror(errno) );
1367 setsockopt(ap->ap_fd, SOL_SOCKET, SO_BROADCAST, &i, sizeof(i));
1368 #endif /* ! __svr4 */
1370 memset( &sat, 0, sizeof( struct sockaddr_at ));
1372 sat.sat_len = sizeof( struct sockaddr_at );
1374 sat.sat_family = AF_APPLETALK;
1375 sat.sat_addr.s_net = iface->i_addr.sat_addr.s_net;
1376 sat.sat_addr.s_node = iface->i_addr.sat_addr.s_node;
1377 sat.sat_port = ap->ap_port;
1379 if ( bind( ap->ap_fd, (struct sockaddr *)&sat,
1380 sizeof( struct sockaddr_at )) < 0 ) {
1381 LOG(log_error, logtype_atalkd, "bind %u.%u:%u: %s",
1382 ntohs( sat.sat_addr.s_net ),
1383 sat.sat_addr.s_node, sat.sat_port, strerror(errno) );
1385 /* remove all interfaces if we have a problem with bind */
1386 for (iface = interfaces; iface; iface = iface->i_next) {
1387 if (ifconfig( iface->i_name, SIOCDIFADDR, &iface->i_addr )) {
1388 #ifdef SIOCATALKDIFADDR
1389 #if (SIOCDIFADDR != SIOCATALKDIFADDR)
1390 ifconfig( iface->i_name, SIOCATALKDIFADDR, &iface->i_addr );
1391 #endif /* SIOCDIFADDR != SIOCATALKDIFADDR */
1392 #endif /* SIOCATALKDIFADDR */
1395 #endif /* SIOCDIFADDR */
1400 /* recalculate nfds and fds */
1402 for ( nfds = 0, iface = interfaces; iface; iface = iface->i_next ) {
1403 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1404 FD_SET( ap->ap_fd, &fds );
1405 if ( ap->ap_fd > nfds ) {
1413 int ifsetallmulti ( iname, set )
1420 memset(&ifr, 0, sizeof(ifr));
1422 if (( sock = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1426 /* get interface config */
1427 strlcpy(ifr.ifr_name, iname, sizeof(ifr.ifr_name));
1428 if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
1433 /* should we set or unset IFF_ALLMULTI */
1435 ifr.ifr_flags |= IFF_ALLMULTI;
1437 ifr.ifr_flags &= ~IFF_ALLMULTI;
1439 /* set interface config */
1440 strlcpy(ifr.ifr_name, iname, sizeof(ifr.ifr_name));
1441 if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) {
1450 int ifconfig( iname, cmd, sa )
1453 struct sockaddr_at *sa;
1458 memset(&ifr, 0, sizeof(ifr));
1459 strcpy( ifr.ifr_name, iname );
1460 ifr.ifr_addr = *(struct sockaddr *)sa;
1462 if (( s = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1465 if ( ioctl( s, cmd, &ifr ) < 0 ) {
1470 if ( cmd == SIOCGIFADDR ) {
1471 *(struct sockaddr *)sa = ifr.ifr_addr;
1476 void dumpconfig( iface )
1477 struct interface *iface;
1481 printf( "%s", iface->i_name );
1482 if ( iface->i_flags & IFACE_RSEED ) {
1483 printf( " -router" );
1484 } else if ( iface->i_flags & IFACE_SEED ) {
1488 if ( iface->i_flags & IFACE_DONTROUTE)
1489 printf( " -dontroute");
1491 printf( " -phase" );
1492 if ( iface->i_flags & IFACE_PHASE1 ) {
1497 printf( " -net %d", ntohs( iface->i_rt->rt_firstnet ));
1498 if ( iface->i_rt->rt_lastnet != iface->i_rt->rt_firstnet ) {
1499 printf( "-%d", ntohs( iface->i_rt->rt_lastnet ));
1501 printf( " -addr %u.%u", ntohs( iface->i_addr.sat_addr.s_net ),
1502 iface->i_addr.sat_addr.s_node );
1503 printf( " -caddr %u.%u", ntohs( iface->i_caddr.sat_addr.s_net ),
1504 iface->i_caddr.sat_addr.s_node );
1505 for ( l = iface->i_rt->rt_zt; l; l = l->l_next ) {
1506 printf( " -zone %.*s", ((struct ziptab *)l->l_data)->zt_len,
1507 ((struct ziptab *)l->l_data)->zt_name );
1515 struct interface *iface;
1516 struct rtmptab *rtmp;
1520 for ( iface = interfaces; iface; iface = iface->i_next ) {
1521 for ( rtmp = iface->i_rt; rtmp; rtmp = rtmp->rt_inext ) {
1522 if ( rtmp->rt_gate == 0 ) {
1523 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
1524 printf( "%u-%u", ntohs( rtmp->rt_firstnet ),
1525 ntohs( rtmp->rt_lastnet ));
1527 printf( "%u", ntohs( rtmp->rt_firstnet ));
1530 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
1531 printf( "%u.%u for %u-%u",
1532 ntohs( rtmp->rt_gate->g_sat.sat_addr.s_net ),
1533 rtmp->rt_gate->g_sat.sat_addr.s_node,
1534 ntohs( rtmp->rt_firstnet ),
1535 ntohs( rtmp->rt_lastnet ));
1537 printf( "%u.%u for %u",
1538 ntohs( rtmp->rt_gate->g_sat.sat_addr.s_net ),
1539 rtmp->rt_gate->g_sat.sat_addr.s_node,
1540 ntohs( rtmp->rt_firstnet ));
1544 if ( rtmp->rt_iprev == 0 && rtmp != iface->i_rt ) {
1548 for ( l = rtmp->rt_zt; l; l = l->l_next ) {
1549 zt = (struct ziptab *)l->l_data;
1550 printf( " %.*s", zt->zt_len, zt->zt_name );
1563 struct interface *iface;
1564 struct rtmptab *rtmp;
1568 for ( zt = ziptab; zt; zt = zt->zt_next ) {
1569 printf( "%.*s", zt->zt_len, zt->zt_name );
1570 for ( l = zt->zt_rt; l; l = l->l_next ) {
1571 rtmp = (struct rtmptab *)l->l_data;
1572 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
1573 printf( " %u-%u", ntohs( rtmp->rt_firstnet ),
1574 ntohs( rtmp->rt_lastnet ));
1576 printf( " %u", ntohs( rtmp->rt_firstnet ));
1578 if ( rtmp->rt_iprev == 0 && rtmp->rt_gate != 0 ) {