2 * Copyright (c) 1990,1993 Regents of The University of Michigan.
3 * All Rights Reserved. See COPYRIGHT.
10 #include <sys/types.h>
11 #include <sys/param.h>
12 #include <sys/socket.h>
13 #if defined( sun ) && defined( __svr4__ )
14 #include </usr/ucbinclude/sys/file.h>
19 #include <sys/resource.h>
20 #include <sys/ioctl.h>
24 #include <net/route.h>
35 #include <netatalk/endian.h>
36 #include <netatalk/at.h>
37 #include <atalk/compat.h>
38 #include <atalk/zip.h>
39 #include <atalk/rtmp.h>
40 #include <atalk/ddp.h>
41 #include <atalk/atp.h>
42 #include <atalk/paths.h>
43 #include <atalk/util.h>
46 #include <sys/sockio.h>
50 #include "interface.h"
58 /* FIXME/SOCKLEN_T: socklen_t is a unix98 feature */
60 #define SOCKLEN_T unsigned int
64 #define WEXITSTATUS(x) ((x).w_retcode)
67 /* linux has a special ioctl for appletalk device destruction. as of
68 * 2.1.57, SIOCDIFADDR works w/ linux. okay, we need to deal with the
69 * fact that SIOCDIFADDR may be defined on linux despite the fact that
71 #if !defined(SIOCDIFADDR) && defined(SIOCATALKDIFADDR)
72 #define SIOCDIFADDR SIOCATALKDIFADDR
75 #define elements(a) (sizeof(a)/sizeof((a)[0]))
79 extern int rtmp_packet();
80 extern int nbp_packet();
81 extern int aep_packet();
82 extern int zip_packet();
86 struct atserv atserv[] = {
87 { "rtmp", 1, rtmp_packet }, /* 0 */
88 { "nbp", 2, nbp_packet }, /* 1 */
89 { "echo", 4, aep_packet }, /* 2 */
90 { "zip", 6, zip_packet }, /* 3 */
92 int atservNATSERV = elements( atserv );
94 struct interface *interfaces = NULL, *ciface = NULL;
96 int debug = 0, quiet = 0, chatty = 0;
97 char *configfile = NULL;
98 int ziptimeout = 0, transition = 0;
99 int stabletimer, stable = 0, newrtmpdata = 0, noparent = 0;
100 static int ninterfaces;
101 int defphase = IFACE_PHASE2;
104 char Packet[ PKTSZ ];
105 char *version = VERSION;
106 static char *pidfile = _PATH_ATALKDLOCK;
111 int readconf( char * );
112 int getifconf( void );
113 int writeconf( char * );
115 /* this is the messiest of the bunch as atalkd can exit pretty much
116 * everywhere. we delete interfaces here instead of in as_down. */
117 static void atalkd_exit(const int i)
120 struct interface *iface;
122 for (iface = interfaces; iface; iface = iface->i_next) {
123 if (ifconfig( iface->i_name, SIOCDIFADDR, &iface->i_addr)) {
124 #ifdef SIOCATALKDIFADDR
125 #if (SIOCDIFADDR != SIOCATALKDIFADDR)
126 if (!ifconfig(iface->i_name, SIOCATALKDIFADDR, &iface->i_addr))
130 syslog( LOG_ERR, "difaddr(%u.%u): %m",
131 ntohs(iface->i_addr.sat_addr.s_net),
132 iface->i_addr.sat_addr.s_node);
137 server_unlock(pidfile);
142 #if !defined( ibm032 ) && !defined( _IBMR2 )
147 struct sockaddr_at sat;
150 struct rtmp_tuple rt;
151 struct atport *ap, *zap, *rap;
152 struct interface *iface, *iface2;
153 struct gate *gate, *fgate = NULL;
154 struct rtmptab *rtmp, *frtmp;
156 char *data, *end, packet[ ATP_BUFSIZ ];
160 memset(&sat, 0, sizeof( struct sockaddr_at ));
161 for ( iface = interfaces; iface; iface = iface->i_next ) {
162 if ( iface->i_flags & IFACE_LOOPBACK ) {
165 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
166 if ( ap->ap_packet == zip_packet ) {
169 if ( ap->ap_packet == rtmp_packet ) {
174 if (( iface->i_flags & ( IFACE_ADDR|IFACE_CONFIG|IFACE_NOROUTER )) ==
176 if ( iface->i_time < 3 ) {
177 if ( iface->i_flags & IFACE_PHASE1 ) {
178 if (rtmp_request( iface ) < 0) {
179 syslog(LOG_ERR, "rtmp_request: %m");
184 if (zip_getnetinfo( iface ) < 0) {
185 syslog(LOG_ERR, "zip_getnetinfo: %m");
192 iface->i_flags |= IFACE_NOROUTER;
193 if ((iface->i_flags & IFACE_ISROUTER)) {
194 if (( iface->i_flags & IFACE_SEED ) == 0 ) {
196 * No seed info, and we've got multiple interfaces.
200 "as_timer multiple interfaces, no seed" );
201 syslog( LOG_INFO, "as_timer can't configure %s",
203 syslog( LOG_INFO, "as_timer waiting for router" );
208 * Complete configuration for iface, and boot next
211 iface->i_flags |= IFACE_CONFIG;
212 for ( zt = iface->i_czt; zt; zt = zt->zt_next ) {
213 if (addzone( iface->i_rt, zt->zt_len,
215 syslog(LOG_ERR, "addzone: %m");
219 if ( iface->i_rt->rt_zt ) {
220 iface->i_rt->rt_flags &= ~RTMPTAB_ZIPQUERY;
221 iface->i_rt->rt_flags |= RTMPTAB_HASZONES;
223 if ( iface->i_flags & IFACE_PHASE1 ) {
225 "as_timer configured %s phase 1 from seed",
227 setaddr( iface, IFACE_PHASE1,
228 iface->i_caddr.sat_addr.s_net,
229 iface->i_addr.sat_addr.s_node,
230 iface->i_caddr.sat_addr.s_net,
231 iface->i_caddr.sat_addr.s_net );
234 "as_timer configured %s phase 2 from seed",
238 if ( looproute( iface, RTMP_ADD )) { /* -1 or 1 */
240 "as_timer: can't route %u.%u to loop: %m",
241 ntohs( iface->i_addr.sat_addr.s_net ),
242 iface->i_addr.sat_addr.s_node );
245 if ( iface == ciface ) {
246 ciface = ciface->i_next;
252 * Configure for no router operation. Wait for a route
253 * to become available in rtmp_packet().
255 syslog( LOG_INFO, "config for no router" );
257 if ( iface->i_flags & IFACE_PHASE2 ) {
258 iface->i_rt->rt_firstnet = 0;
259 iface->i_rt->rt_lastnet = htons( STARTUP_LASTNET );
260 setaddr( iface, IFACE_PHASE2,
261 iface->i_addr.sat_addr.s_net,
262 iface->i_addr.sat_addr.s_node,
263 0, htons( STARTUP_LASTNET ));
265 if ( looproute( iface, RTMP_ADD ) ) { /* -1 or 1 */
267 "as_timer: can't route %u.%u to loopback: %m",
268 ntohs( iface->i_addr.sat_addr.s_net ),
269 iface->i_addr.sat_addr.s_node );
273 if ( iface == ciface ) {
274 ciface = ciface->i_next;
281 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
283 free( (caddr_t)fgate );
288 data = packet + 1 + sizeof( struct ziphdr );
289 end = packet + sizeof( packet );
292 sat.sat_port = zap->ap_port;
295 * Perform timeouts on routers. If we've only got one
296 * interface, we'll use these timeouts to decide that
297 * our zone has gone away.
299 if ( ++gate->g_state >= RTMPTAB_BAD ) {
300 syslog( LOG_INFO, "as_timer gateway %u.%u down",
301 ntohs( gate->g_sat.sat_addr.s_net ),
302 gate->g_sat.sat_addr.s_node );
305 frtmp = rtmp->rt_next;
306 if ( rtmp->rt_hops == RTMPHOPS_POISON ||
307 rtmp->rt_iprev == 0 ) {
310 rtmp->rt_hops = RTMPHOPS_POISON;
311 if ((cc = rtmp_replace( rtmp )) < 0) {
312 syslog(LOG_ERR, "rtmp_replace: %m");
316 gate->g_state = rtmp->rt_state = RTMPTAB_GOOD;
321 if ( gate->g_rt == 0 ) {
322 if ( gate->g_prev == 0 ) {
323 gate->g_iface->i_gate = gate->g_next;
325 gate->g_prev->g_next = gate->g_next;
327 if ( gate->g_next != 0 ) {
328 gate->g_next->g_prev = gate->g_prev;
330 fgate = gate; /* can't free here, just mark it */
333 * If this is the last router on the only interface,
334 * reconfigure our netrange. By marking the interface
335 * as having no router, we will notice when a router
338 * XXX: actually, we always reconfigure an interface
339 * if we're not a seed router.
342 if ( gate->g_iface->i_gate == 0 &&
343 ((iface->i_flags & IFACE_SEED) == 0)) {
344 gate->g_iface->i_flags |= IFACE_NOROUTER;
345 gate->g_iface->i_flags &= ~IFACE_CONFIG;
347 /* get rid of any zones associated with this iface */
348 if (gate->g_iface->i_rt->rt_zt) {
349 rtmp_delzonemap(gate->g_iface->i_rt);
350 gate->g_iface->i_rt->rt_flags &= ~RTMPTAB_HASZONES;
353 syslog( LOG_INFO, "as_timer last gateway down" );
355 /* Set netrange to 0-fffe. */
356 if ( gate->g_iface->i_flags & IFACE_PHASE2 ) {
357 gate->g_iface->i_rt->rt_firstnet = 0;
358 gate->g_iface->i_rt->rt_lastnet =
359 htons( STARTUP_LASTNET );
360 setaddr( iface, IFACE_PHASE2,
361 iface->i_addr.sat_addr.s_net,
362 iface->i_addr.sat_addr.s_node,
363 0, htons( STARTUP_LASTNET ));
370 * If we don't have a zone for our interface yet, ask for
371 * it from any router (all routers) on the interface.
373 if (( iface->i_rt->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
374 iface->i_rt->rt_flags |= RTMPTAB_ZIPQUERY;
375 memcpy( data, &iface->i_rt->rt_firstnet, sizeof( u_short ));
376 data += sizeof( u_short );
383 * Delete old routing tuples.
385 if ( rtmp->rt_state != RTMPTAB_PERM ) {
390 * We've not been updated for this route in a while. If
391 * it's not in use, go ahead and remove it. If it is in
392 * use, mark the route as down (POISON), and look for a
393 * better route. If one is found, delete this route and use
394 * the new one. If it's not found, mark the route as GOOD
395 * (so we'll propogate our poison) and delete it the next
396 * time it becomes BAD.
398 if ( rtmp->rt_state >= RTMPTAB_BAD ) {
399 frtmp = rtmp->rt_next;
400 if ( rtmp->rt_iprev == 0 ) { /* not in use */
402 } else { /* in use */
403 if ( rtmp->rt_hops == RTMPHOPS_POISON ) {
406 rtmp->rt_hops = RTMPHOPS_POISON;
407 if ((cc = rtmp_replace( rtmp )) < 0) {
408 syslog(LOG_ERR, "rtmp_replace: %m");
412 rtmp->rt_state = RTMPTAB_GOOD;
422 if ( rtmp->rt_iprev &&
423 ( rtmp->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
424 if ( data + sizeof( u_short ) > end || n == 255 ) {
425 /* send what we've got */
426 zh.zh_op = ZIPOP_QUERY;
430 *data++ = DDPTYPE_ZIP;
431 memcpy( data, &zh, sizeof( struct ziphdr ));
433 if ( sendto( zap->ap_fd, packet, cc, 0,
434 (struct sockaddr *)&sat,
435 sizeof( struct sockaddr_at )) < 0 ) {
436 syslog( LOG_ERR, "as_timer sendto: %m" );
441 data = packet + 1 + sizeof( struct ziphdr );
442 end = packet + sizeof( packet );
446 * rt_nzq is number of ZIP Queries we've issued for a
447 * given netrange. If we've got ziptimeout on, we
448 * will only ask 3 times for any given netrange.
449 * Interestingly enough, since rt_nzq is a u_char,
450 * it will overflow after a while. This means we will
451 * periodically ask for nets that we've decided not to
452 * ask about, and warn that we can't get it's zone.
454 if ( rtmp->rt_nzq++ == 3 ) {
455 syslog( LOG_INFO, "as_timer can't get zone for %u",
456 ntohs( rtmp->rt_firstnet ));
458 if ( rtmp->rt_nzq > 3 ) {
460 rtmp = rtmp->rt_next;
466 rtmp->rt_flags |= RTMPTAB_ZIPQUERY;
467 memcpy( data, &rtmp->rt_firstnet, sizeof( u_short ));
468 data += sizeof( u_short );
471 rtmp = rtmp->rt_next;
474 /* send what we've got */
476 zh.zh_op = ZIPOP_QUERY;
480 *data++ = DDPTYPE_ZIP;
481 memcpy( data, &zh, sizeof( struct ziphdr ));
483 if ( sendto( zap->ap_fd, packet, cc, 0, (struct sockaddr *)&sat,
484 sizeof( struct sockaddr_at )) < 0 ) {
485 syslog( LOG_ERR, "as_timer sendto: %m" );
490 free( (caddr_t)fgate );
495 * Send RTMP broadcasts if we have multiple interfaces or our
496 * interface is configured as a router.
498 if ((iface->i_flags & IFACE_ISROUTER)) {
500 sat.sat_len = sizeof( struct sockaddr_at );
502 sat.sat_family = AF_APPLETALK;
503 sat.sat_addr.s_net = ATADDR_ANYNET;
504 sat.sat_addr.s_node = ATADDR_BCAST;
505 sat.sat_port = rap->ap_port;
508 end = data + sizeof( packet );
509 *data++ = DDPTYPE_RTMPRD;
510 rh.rh_net = iface->i_addr.sat_addr.s_net;
512 rh.rh_node = iface->i_addr.sat_addr.s_node;
513 memcpy( data, &rh, sizeof( struct rtmp_head ));
514 data += sizeof( struct rtmp_head );
518 if ( iface->i_flags & IFACE_PHASE1 ) {
521 memcpy( data, &rt, SZ_RTMPTUPLE );
522 data += SZ_RTMPTUPLE;
524 rt.rt_net = iface->i_rt->rt_firstnet;
526 memcpy( data, &rt, SZ_RTMPTUPLE );
527 data += SZ_RTMPTUPLE;
529 rt.rt_net = iface->i_rt->rt_lastnet;
531 memcpy( data, &rt, SZ_RTMPTUPLE );
532 data += SZ_RTMPTUPLE;
535 for ( iface2 = interfaces; iface2; iface2 = iface2->i_next ) {
537 /* XXX: there used to be a bit checking against iface ==
538 iface2. also, we don't want to send an rtmp broadcast
539 to an interface that doesn't want it. */
540 if ((( iface2->i_flags & IFACE_CONFIG ) == 0) ||
541 ((iface2->i_flags & IFACE_ISROUTER) == 0)) {
545 * Fill in tuples. Always send the same thing, regardless
546 * of the phase of the destination. Routers who don't
547 * understand extended rtmp packets will toss extended
548 * tuples because their distance will have the high bit set.
550 for ( rtmp = iface2->i_rt; rtmp; rtmp = rtmp->rt_inext ) {
551 /* don't broadcast routes we have no zone for */
552 if ( rtmp->rt_zt == 0 ||
553 ( rtmp->rt_flags & RTMPTAB_ZIPQUERY ) ||
554 ( rtmp->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
558 if ((( rtmp->rt_flags & RTMPTAB_EXTENDED ) &&
559 data + 2 * SZ_RTMPTUPLE > end ) ||
560 data + SZ_RTMPTUPLE > end ) {
561 if ( sendto( rap->ap_fd, packet, data - packet, 0,
562 (struct sockaddr *)&sat,
563 sizeof( struct sockaddr_at )) < 0 ) {
564 syslog( LOG_ERR, "as_timer sendto %u.%u (%u): %m",
565 ntohs( sat.sat_addr.s_net ),
567 ntohs( iface->i_rt->rt_firstnet ));
570 if ( iface->i_flags & IFACE_PHASE2 ) {
571 data = packet + 1 + sizeof( struct rtmp_head ) +
574 data = packet + 1 + sizeof( struct rtmp_head ) +
580 rt.rt_net = rtmp->rt_firstnet;
581 rt.rt_dist = rtmp->rt_hops;
582 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
585 memcpy( data, &rt, SZ_RTMPTUPLE );
586 data += SZ_RTMPTUPLE;
588 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
589 rt.rt_net = rtmp->rt_lastnet;
591 memcpy( data, &rt, SZ_RTMPTUPLE );
592 data += SZ_RTMPTUPLE;
600 if ( sendto( rap->ap_fd, packet, data - packet, 0,
601 (struct sockaddr *)&sat,
602 sizeof( struct sockaddr_at )) < 0 ) {
603 syslog( LOG_ERR, "as_timer sendto %u.%u (%u): %m",
604 ntohs( sat.sat_addr.s_net ),
606 ntohs( iface->i_rt->rt_firstnet ));
613 * Check if we're stable. Each time we configure an interface, we
614 * sent stabletimer to UNSTABLE. If stabletimer ever gets to
615 * STABLEANYWAY, we give up and decide to "be" stable anyway.
616 * Normally, we wait for stabletimer get <= STABLE with no new rtmp
617 * data and all zip data complete.
620 if ( stabletimer <= STABLE && !newrtmpdata && !sentzipq ) {
621 /* write out config file */
623 writeconf( configfile );
625 if ( stabletimer-- <= STABLEANYWAY ) {
631 if ( stable && !noparent ) {
633 syslog( LOG_INFO, "ready %d/%d/%d", stabletimer, newrtmpdata,
637 * Seems like we could get here more than once...
639 if ( kill( getpid(), SIGSTOP ) < 0 ) {
640 syslog( LOG_ERR, "as_timer: kill-self failed!" );
654 * Consistency check...
658 struct rtmptab *rtmp;
659 struct list *lr, *lz;
662 for ( zt = ziptab; zt; zt = zt->zt_next ) {
663 for ( lr = zt->zt_rt; lr; lr = lr->l_next ) {
664 rtmp = (struct rtmptab *)lr->l_data;
665 if ( rtmp->rt_iprev == 0 && rtmp->rt_gate != 0 ) {
666 syslog( LOG_ERR, "%.*s has %u-%u (unused)\n",
667 zt->zt_len, zt->zt_name, ntohs( rtmp->rt_firstnet ),
668 ntohs( rtmp->rt_lastnet ));
671 for ( lz = rtmp->rt_zt; lz; lz = lz->l_next ) {
672 if ( zt == (struct ziptab *)lz->l_data ) {
677 syslog( LOG_ERR, "no map from %u-%u to %.*s\n",
678 ntohs( rtmp->rt_firstnet ),
679 ntohs( rtmp->rt_lastnet ),
680 zt->zt_len, zt->zt_name );
688 #if !defined( ibm032 ) && !defined( _IBMR2 )
693 struct interface *iface;
700 if (( rtmpdebug = fopen( _PATH_ATALKDEBUG, "w" )) == NULL ) {
701 syslog( LOG_ERR, "rtmp: %m" );
704 for ( iface = interfaces; iface; iface = iface->i_next ) {
705 fprintf( rtmpdebug, "interface %s %u.%u ", iface->i_name,
706 ntohs( iface->i_addr.sat_addr.s_net ),
707 iface->i_addr.sat_addr.s_node );
708 if ( iface->i_flags & IFACE_PHASE1 ) {
709 putc( '1', rtmpdebug );
711 if ( iface->i_flags & IFACE_PHASE2 ) {
712 putc( '2', rtmpdebug );
714 if ( iface->i_flags & IFACE_RSEED ) {
715 putc( 'R', rtmpdebug );
717 if ( iface->i_flags & IFACE_SEED ) {
718 putc( 'S', rtmpdebug );
720 if ( iface->i_flags & IFACE_DONTROUTE ) {
721 putc( 'D', rtmpdebug );
723 if ( iface->i_flags & IFACE_ADDR ) {
724 putc( 'A', rtmpdebug );
726 if ( iface->i_flags & IFACE_CONFIG ) {
727 putc( 'C', rtmpdebug );
729 if ( iface->i_flags & IFACE_NOROUTER ) {
730 putc( 'N', rtmpdebug );
732 if ( iface->i_flags & IFACE_LOOP ) {
733 putc( 'L', rtmpdebug );
735 putc( '\n', rtmpdebug );
738 fprintf( rtmpdebug, "\t%u-%u ",
739 ntohs( iface->i_rt->rt_firstnet ),
740 ntohs( iface->i_rt->rt_lastnet ));
741 if ( iface->i_rt->rt_flags & RTMPTAB_ZIPQUERY ) {
742 putc( 'q', rtmpdebug );
744 if ( iface->i_rt->rt_flags & RTMPTAB_HASZONES ) {
745 putc( 'z', rtmpdebug );
747 if ( iface->i_rt->rt_flags & RTMPTAB_EXTENDED ) {
748 putc( 'x', rtmpdebug );
750 putc( 'i', rtmpdebug );
751 for ( l = iface->i_rt->rt_zt; l; l = l->l_next ) {
752 zt = (struct ziptab *)l->l_data;
753 fprintf( rtmpdebug, " '%.*s'", zt->zt_len, zt->zt_name );
755 fprintf( rtmpdebug, "\n" );
758 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
759 fprintf( rtmpdebug, "gate %u.%u %X\n",
760 ntohs( gate->g_sat.sat_addr.s_net ),
761 gate->g_sat.sat_addr.s_node, gate->g_state );
762 for ( rt = gate->g_rt; rt; rt = rt->rt_next ) {
763 fprintf( rtmpdebug, "\t%u-%u ", ntohs( rt->rt_firstnet ),
764 ntohs( rt->rt_lastnet ));
765 if ( rt->rt_flags & RTMPTAB_ZIPQUERY ) {
766 putc( 'q', rtmpdebug );
768 if ( rt->rt_flags & RTMPTAB_HASZONES ) {
769 putc( 'z', rtmpdebug );
771 if ( rt->rt_flags & RTMPTAB_EXTENDED ) {
772 putc( 'x', rtmpdebug );
774 if ( rt->rt_iprev ) {
775 putc( 'i', rtmpdebug );
777 for ( l = rt->rt_zt; l; l = l->l_next ) {
778 zt = (struct ziptab *)l->l_data;
779 fprintf( rtmpdebug, " '%.*s'", zt->zt_len, zt->zt_name );
781 fprintf( rtmpdebug, "\n" );
790 * Called when SIGTERM is recieved. Remove all routes and then exit.
792 #if !defined( ibm032 ) && !defined( _IBMR2 )
797 struct interface *iface;
801 for ( iface = interfaces; iface; iface = iface->i_next ) {
802 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
803 for ( rt = gate->g_rt; rt; rt = rt->rt_next ) {
804 if ( rt->rt_iprev ) {
805 if ( gateroute( RTMP_DEL, rt ) < 0 ) {
806 syslog( LOG_ERR, "as_down remove %u-%u failed: %m",
807 ntohs( rt->rt_firstnet ),
808 ntohs( rt->rt_lastnet ));
813 if ( iface->i_flags & IFACE_LOOP ) {
814 if (looproute( iface, RTMP_DEL )) {
815 syslog( LOG_ERR, "as_down remove %s %u.%u failed: %m",
816 iface->i_name, ntohs( iface->i_addr.sat_addr.s_net ),
817 iface->i_addr.sat_addr.s_node );
822 syslog( LOG_INFO, "done" );
833 struct sockaddr_at sat;
836 struct interface *iface;
845 while (( c = getopt( ac, av, "12qsdtf:P:" )) != EOF ) {
848 defphase = IFACE_PHASE1;
852 defphase = IFACE_PHASE2;
863 case 'q' : /* don't seed */
867 case 's' : /* seed */
871 case 't' : /* transition */
875 case 'P' : /* pid file */
880 fprintf( stderr, "Unknown option -- '%c'\n", c );
884 if ( optind != ac ) {
885 fprintf( stderr, "Too many arguments.\n" );
889 if (( prog = strrchr( av[ 0 ], '/' )) == NULL ) {
896 * Configure loop back address first, so appearances of "lo0" in
897 * the config file fail. Also insures that lo0 gets configured,
898 * even if there's some hangup during configuration of some
901 if (( interfaces = newiface( LOOPIFACE )) == NULL ) {
902 perror( "newiface" );
905 interfaces->i_flags |= IFACE_PHASE2 | IFACE_LOOPBACK;
908 * Check our initial configuration before we fork. This way we can
909 * complain about syntax errors on stdout.
911 * Basically, if we're going to read our config file, we should read
912 * it and initialize our data structures. If we're not going to read
913 * our config file, use GIFCONF to initialize our data structures.
915 if ( readconf( configfile ) < 0 && getifconf() < 0 ) {
916 fprintf( stderr, "%s: can't get interfaces, exiting.\n", prog );
920 /* we need to count up our interfaces so that we can simplify things
921 * later. we also need to figure out if we have more than one interface
922 * that is routing. */
923 for (i = 0, ninterfaces = 0, iface = interfaces; iface;
924 iface=iface->i_next) {
925 if (iface->i_flags & IFACE_DONTROUTE)
929 i = ninterfaces - i; /* number of routable interfaces */
932 * At this point, we have (at least partially) initialized data
933 * structures. Fill in what we can and verify that nothing is obviously
936 for (iface = interfaces; iface; iface = iface->i_next) {
937 /* Apply the default phase */
938 if (( iface->i_flags & IFACE_PHASE1 ) == 0 &&
939 ( iface->i_flags & IFACE_PHASE2 ) == 0 ) {
940 iface->i_flags |= defphase;
943 /* set up router flag information. if we have multiple interfaces
944 * and DONTROUTE isn't set, set up ROUTER. i is the number of
945 * interfaces that don't have the DONTROUTE flag set. */
946 if ((i > IFBASE) && ((iface->i_flags & IFACE_DONTROUTE) == 0)) {
947 iface->i_flags |= IFACE_ISROUTER;
950 /* Set default addresses */
951 if ( iface->i_rt == NULL ) {
952 if (( iface->i_rt = newrt(iface)) == NULL ) {
957 if ( iface->i_flags & IFACE_PHASE1 ) {
958 iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet =
959 iface->i_caddr.sat_addr.s_net;
961 if ( iface->i_caddr.sat_addr.s_net != ATADDR_ANYNET ||
962 ( iface->i_flags & IFACE_LOOPBACK )) {
963 iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet =
964 iface->i_caddr.sat_addr.s_net;
966 iface->i_rt->rt_firstnet = htons( STARTUP_FIRSTNET );
967 iface->i_rt->rt_lastnet = htons( STARTUP_LASTNET );
972 if (( iface->i_flags & IFACE_PHASE1 ) == 0 ) {
973 iface->i_rt->rt_flags |= RTMPTAB_EXTENDED;
976 if ( iface->i_caddr.sat_addr.s_net == ATADDR_ANYNET ) {
977 iface->i_caddr.sat_addr.s_net = iface->i_rt->rt_firstnet;
981 dumpconfig( iface ); /* probably needs args */
986 * A little consistency check...
988 if ( ninterfaces < IFBASE ) {
989 fprintf( stderr, "%s: zero interfaces, exiting.\n", prog );
993 /* do this here so that we can use ifconfig */
996 fprintf(stderr, "can't establish STREAMS plumbing, exiting.\n" );
1001 /* delete pre-existing interface addresses. */
1003 for (iface = interfaces; iface; iface = iface->i_next) {
1004 if (ifconfig(iface->i_name, SIOCDIFADDR, &iface->i_addr)) {
1005 #ifdef SIOCATALKDIFADDR
1006 #if (SIOCDIFADDR != SIOCATALKDIFADDR)
1007 ifconfig(iface->i_name, SIOCATALKDIFADDR, &iface->i_addr);
1015 * Disassociate. The child will send itself a signal when it is
1016 * stable. This indicates that other processes may begin using
1019 switch (i = server_lock("atalkd", pidfile, debug)) {
1024 default: /* parent */
1026 * Wait for the child to send itself a SIGSTOP, after which
1027 * we send it a SIGCONT and exit ourself.
1029 if ( wait3( &status, WUNTRACED, (struct rusage *)0 ) != i) {
1030 perror( "wait3" ); /* Child died? */
1033 if ( !WIFSTOPPED( status )) {
1034 fprintf( stderr, "AppleTalk not up! Check your syslog for the reason." );
1035 if ( WIFEXITED( status )) {
1036 fprintf( stderr, " Child exited with %d.\n",
1037 WEXITSTATUS( status ));
1039 fprintf( stderr, " Child died.\n" );
1043 if ( kill(i, SIGCONT ) < 0 ) {
1051 openlog( prog, LOG_PID );
1053 openlog( prog, LOG_PID, LOG_DAEMON );
1056 syslog( LOG_INFO, "restart (%s)", version );
1059 * Socket for use in routing ioctl()s. Can't add routes to our
1060 * interfaces until we have our routing socket.
1063 if (( rtfd = socket( PF_ROUTE, SOCK_RAW, AF_APPLETALK )) < 0 ) {
1064 syslog( LOG_ERR, "route socket: %m" );
1067 if ( shutdown( rtfd, 0 ) < 0 ) {
1068 syslog( LOG_ERR, "route shutdown: %m" );
1072 if (( rtfd = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1073 syslog( LOG_ERR, "route socket: %m" );
1078 memset(&sv, 0, sizeof(sv));
1079 sv.sa_handler = as_down;
1080 sigemptyset( &sv.sa_mask );
1081 sigaddset( &sv.sa_mask, SIGUSR1 );
1082 sigaddset( &sv.sa_mask, SIGALRM );
1083 sigaddset( &sv.sa_mask, SIGTERM );
1084 sv.sa_flags = SA_RESTART;
1085 if ( sigaction( SIGTERM, &sv, NULL) < 0 ) {
1086 syslog( LOG_ERR, "sigterm: %m" );
1090 sv.sa_handler = as_debug;
1091 sigemptyset( &sv.sa_mask );
1092 sigaddset( &sv.sa_mask, SIGUSR1 );
1093 sigaddset( &sv.sa_mask, SIGALRM );
1094 sigaddset( &sv.sa_mask, SIGTERM );
1095 sv.sa_flags = SA_RESTART;
1096 if ( sigaction( SIGUSR1, &sv, NULL) < 0 ) {
1097 syslog( LOG_ERR, "sigusr1: %m" );
1101 sv.sa_handler = as_timer;
1102 sigemptyset( &sv.sa_mask );
1103 sigaddset( &sv.sa_mask, SIGUSR1 );
1104 sigaddset( &sv.sa_mask, SIGALRM );
1105 sigaddset( &sv.sa_mask, SIGTERM );
1106 sv.sa_flags = SA_RESTART;
1107 if ( sigaction( SIGALRM, &sv, NULL) < 0 ) {
1108 syslog( LOG_ERR, "sigalrm: %m" );
1112 it.it_interval.tv_sec = 10L;
1113 it.it_interval.tv_usec = 0L;
1114 it.it_value.tv_sec = 10L;
1115 it.it_value.tv_usec = 0L;
1116 if ( setitimer( ITIMER_REAL, &it, NULL) < 0 ) {
1117 syslog( LOG_ERR, "setitimer: %m" );
1121 ciface = interfaces;
1125 if ( select( nfds, &readfds, NULL, NULL, NULL) < 0 ) {
1126 if ( errno == EINTR ) {
1130 syslog( LOG_ERR, "select: %m" );
1135 for ( iface = interfaces; iface; iface = iface->i_next ) {
1136 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1137 if ( FD_ISSET( ap->ap_fd, &readfds )) {
1138 if ( ap->ap_packet ) {
1139 fromlen = sizeof( struct sockaddr_at );
1140 if (( c = recvfrom( ap->ap_fd, Packet, sizeof( Packet ),
1141 0, (struct sockaddr *)&sat, &fromlen )) < 0 ) {
1142 syslog( LOG_ERR, "recvfrom: %m" );
1147 printf( "packet from %u.%u on %s (%x) %d (%d)\n",
1148 ntohs( sat.sat_addr.s_net ),
1149 sat.sat_addr.s_node, iface->i_name,
1150 iface->i_flags, ap->ap_port, ap->ap_fd );
1151 bprint( Packet, c );
1155 if ( sighold( SIGALRM ) || sighold( SIGUSR1 )) {
1156 syslog( LOG_ERR, "sighold: %m" );
1160 mask = sigsetmask( sigmask( SIGALRM ) |
1161 sigmask( SIGUSR1 ));
1163 if (( *ap->ap_packet )( ap, &sat, Packet, c ) < 0) {
1164 syslog(LOG_ERR, "ap->ap_packet: %m");
1172 if ( sigrelse( SIGUSR1 ) || sigrelse( SIGALRM )) {
1173 syslog( LOG_ERR, "sigrelse: %m" );
1187 * This code is called (from main(), as_timer(), zip_packet(),
1188 * and rtmp_packet()) to set the initial "bootstrapping" address
1191 void bootaddr( iface )
1192 struct interface *iface;
1199 if ( iface->i_flags & IFACE_ADDR ) {
1200 syslog( LOG_ERR, "bootaddr OOPS!" );
1204 if ( iface->i_flags & IFACE_PHASE1 ) {
1205 setaddr( iface, IFACE_PHASE1, 0,
1206 iface->i_caddr.sat_addr.s_node, 0, 0 );
1208 if ( iface->i_flags & IFACE_LOOPBACK ) {
1209 iface->i_flags |= IFACE_CONFIG | IFACE_ADDR;
1210 if ( ciface == iface ) {
1211 ciface = ciface->i_next;
1215 } else if (rtmp_request( iface ) < 0) {
1216 syslog(LOG_ERR, "bootaddr (rtmp_request): %m");
1221 setaddr( iface, IFACE_PHASE2, iface->i_caddr.sat_addr.s_net,
1222 iface->i_caddr.sat_addr.s_node,
1223 iface->i_rt->rt_firstnet, iface->i_rt->rt_lastnet );
1225 if ( iface->i_flags & IFACE_LOOPBACK ) {
1226 iface->i_flags |= IFACE_CONFIG | IFACE_ADDR;
1227 if ( ciface == iface ) {
1228 ciface = ciface->i_next;
1232 } else if (zip_getnetinfo( iface ) < 0) {
1233 syslog(LOG_ERR, "bootaddr (zip_getnetinfo): %m");
1238 iface->i_flags |= IFACE_ADDR;
1239 stabletimer = UNSTABLE;
1245 * to manage the i_ports field and the fds for select().
1247 void setaddr( iface, phase, net, node, first, last )
1248 struct interface *iface;
1252 u_int16_t first, last;
1258 struct sockaddr_at sat;
1261 if ( iface->i_ports == NULL ) { /* allocate port structures */
1262 for ( i = 0, as = atserv; i < atservNATSERV; i++, as++ ) {
1263 if (( se = getservbyname( as->as_name, "ddp" )) == NULL ) {
1264 syslog( LOG_INFO, "%s: service unknown", as->as_name );
1266 as->as_port = ntohs( se->s_port );
1268 if (( ap = (struct atport *)malloc( sizeof( struct atport ))) ==
1270 syslog( LOG_ERR, "malloc: %m" );
1274 ap->ap_next = iface->i_ports;
1275 ap->ap_iface = iface;
1276 ap->ap_port = as->as_port;
1277 ap->ap_packet = as->as_packet;
1279 iface->i_ports = ap;
1281 } else { /* close ports */
1282 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1283 (void)close( ap->ap_fd );
1288 iface->i_addr.sat_len = sizeof( struct sockaddr_at );
1290 iface->i_addr.sat_family = AF_APPLETALK;
1291 iface->i_addr.sat_addr.s_net = net;
1292 iface->i_addr.sat_addr.s_node = node;
1294 nr.nr_phase = phase;
1295 nr.nr_firstnet = first;
1296 nr.nr_lastnet = last;
1297 memcpy( iface->i_addr.sat_zero, &nr, sizeof( struct netrange ));
1299 if ( ifconfig( iface->i_name, SIOCSIFADDR, &iface->i_addr )) {
1300 syslog( LOG_ERR, "setifaddr: %s (%u-%u): %m. try specifying a \
1301 smaller net range.", iface->i_name, ntohs(first), ntohs(last));
1304 if ( ifconfig( iface->i_name, SIOCGIFADDR, &iface->i_addr )) {
1305 syslog( LOG_ERR, "getifaddr: %s: %m", iface->i_name );
1310 i = 1; /* enable broadcasts */
1311 #if defined(__svr4__)
1312 syslog(LOG_INFO, "setsockopt incompatible w/ Solaris STREAMS module.");
1314 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1315 if (( ap->ap_fd = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1316 syslog( LOG_ERR, "socket: %m" );
1319 #if !defined(__svr4__)
1320 setsockopt(ap->ap_fd, SOL_SOCKET, SO_BROADCAST, &i, sizeof(i));
1323 memset( &sat, 0, sizeof( struct sockaddr_at ));
1325 sat.sat_len = sizeof( struct sockaddr_at );
1327 sat.sat_family = AF_APPLETALK;
1328 sat.sat_addr.s_net = iface->i_addr.sat_addr.s_net;
1329 sat.sat_addr.s_node = iface->i_addr.sat_addr.s_node;
1330 sat.sat_port = ap->ap_port;
1332 if ( bind( ap->ap_fd, (struct sockaddr *)&sat,
1333 sizeof( struct sockaddr_at )) < 0 ) {
1334 syslog( LOG_ERR, "bind %u.%u:%u: %m",
1335 ntohs( sat.sat_addr.s_net ),
1336 sat.sat_addr.s_node, sat.sat_port );
1338 /* remove all interfaces if we have a problem with bind */
1339 for (iface = interfaces; iface; iface = iface->i_next) {
1340 if (ifconfig( iface->i_name, SIOCDIFADDR, &iface->i_addr )) {
1341 #ifdef SIOCATALKDIFADDR
1342 #if (SIOCDIFADDR != SIOCATALKDIFADDR)
1343 ifconfig( iface->i_name, SIOCATALKDIFADDR, &iface->i_addr );
1353 /* recalculate nfds and fds */
1355 for ( nfds = 0, iface = interfaces; iface; iface = iface->i_next ) {
1356 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1357 FD_SET( ap->ap_fd, &fds );
1358 if ( ap->ap_fd > nfds ) {
1366 int ifconfig( iname, cmd, sa )
1369 struct sockaddr_at *sa;
1374 memset(&ifr, 0, sizeof(ifr));
1375 strcpy( ifr.ifr_name, iname );
1376 ifr.ifr_addr = *(struct sockaddr *)sa;
1378 if (( s = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1381 if ( ioctl( s, cmd, &ifr ) < 0 ) {
1386 if ( cmd == SIOCGIFADDR ) {
1387 *(struct sockaddr *)sa = ifr.ifr_addr;
1392 void dumpconfig( iface )
1393 struct interface *iface;
1397 printf( "%s", iface->i_name );
1398 if ( iface->i_flags & IFACE_RSEED ) {
1399 printf( " -router" );
1400 } else if ( iface->i_flags & IFACE_SEED ) {
1404 if ( iface->i_flags & IFACE_DONTROUTE)
1405 printf( " -dontroute");
1407 printf( " -phase" );
1408 if ( iface->i_flags & IFACE_PHASE1 ) {
1413 printf( " -net %d", ntohs( iface->i_rt->rt_firstnet ));
1414 if ( iface->i_rt->rt_lastnet != iface->i_rt->rt_firstnet ) {
1415 printf( "-%d", ntohs( iface->i_rt->rt_lastnet ));
1417 printf( " -addr %u.%u", ntohs( iface->i_addr.sat_addr.s_net ),
1418 iface->i_addr.sat_addr.s_node );
1419 printf( " -caddr %u.%u", ntohs( iface->i_caddr.sat_addr.s_net ),
1420 iface->i_caddr.sat_addr.s_node );
1421 for ( l = iface->i_rt->rt_zt; l; l = l->l_next ) {
1422 printf( " -zone %.*s", ((struct ziptab *)l->l_data)->zt_len,
1423 ((struct ziptab *)l->l_data)->zt_name );
1431 struct interface *iface;
1432 struct rtmptab *rtmp;
1436 for ( iface = interfaces; iface; iface = iface->i_next ) {
1437 for ( rtmp = iface->i_rt; rtmp; rtmp = rtmp->rt_inext ) {
1438 if ( rtmp->rt_gate == 0 ) {
1439 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
1440 printf( "%u-%u", ntohs( rtmp->rt_firstnet ),
1441 ntohs( rtmp->rt_lastnet ));
1443 printf( "%u", ntohs( rtmp->rt_firstnet ));
1446 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
1447 printf( "%u.%u for %u-%u",
1448 ntohs( rtmp->rt_gate->g_sat.sat_addr.s_net ),
1449 rtmp->rt_gate->g_sat.sat_addr.s_node,
1450 ntohs( rtmp->rt_firstnet ),
1451 ntohs( rtmp->rt_lastnet ));
1453 printf( "%u.%u for %u",
1454 ntohs( rtmp->rt_gate->g_sat.sat_addr.s_net ),
1455 rtmp->rt_gate->g_sat.sat_addr.s_node,
1456 ntohs( rtmp->rt_firstnet ));
1460 if ( rtmp->rt_iprev == 0 && rtmp != iface->i_rt ) {
1464 for ( l = rtmp->rt_zt; l; l = l->l_next ) {
1465 zt = (struct ziptab *)l->l_data;
1466 printf( " %.*s", zt->zt_len, zt->zt_name );
1479 struct interface *iface;
1480 struct rtmptab *rtmp;
1484 for ( zt = ziptab; zt; zt = zt->zt_next ) {
1485 printf( "%.*s", zt->zt_len, zt->zt_name );
1486 for ( l = zt->zt_rt; l; l = l->l_next ) {
1487 rtmp = (struct rtmptab *)l->l_data;
1488 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
1489 printf( " %u-%u", ntohs( rtmp->rt_firstnet ),
1490 ntohs( rtmp->rt_lastnet ));
1492 printf( " %u", ntohs( rtmp->rt_firstnet ));
1494 if ( rtmp->rt_iprev == 0 && rtmp->rt_gate != 0 ) {