]> arthur.barton.de Git - netatalk.git/blob - etc/atalkd/main.c
Warning fixes.
[netatalk.git] / etc / atalkd / main.c
1 /*
2  * Copyright (c) 1990,1993 Regents of The University of Michigan.
3  * All Rights Reserved. See COPYRIGHT.
4  */
5
6 #ifdef HAVE_CONFIG_H
7 #include "config.h"
8 #endif
9
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>
15 #else sun __svr4__
16 #include <sys/file.h>
17 #endif sun __svr4__
18 #include <sys/time.h>
19 #include <sys/resource.h>
20 #include <sys/ioctl.h>
21 #include <sys/wait.h>
22 #include <errno.h>
23 #include <net/if.h>
24 #include <net/route.h>
25
26 #include <signal.h>
27 #include <syslog.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <netdb.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34
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>
44
45 #ifdef __svr4__
46 #include <sys/sockio.h>
47 #include <termios.h>
48 #endif __svr4__
49
50 #include "interface.h"
51 #include "gate.h"
52 #include "list.h"
53 #include "rtmp.h"
54 #include "zip.h"
55 #include "atserv.h"
56 #include "main.h"
57
58 /* Forward Declarations */
59 int ifconfig(const char *iname, unsigned long cmd, struct sockaddr_at *sa);
60
61 /* FIXME/SOCKLEN_T: socklen_t is a unix98 feature */
62 #ifndef SOCKLEN_T
63 #define SOCKLEN_T unsigned int
64 #endif
65
66 #ifndef WEXITSTATUS
67 #define WEXITSTATUS(x)  ((x).w_retcode)
68 #endif WEXITSTATUS
69
70 /* linux has a special ioctl for appletalk device destruction.  as of
71  * 2.1.57, SIOCDIFADDR works w/ linux. okay, we need to deal with the
72  * fact that SIOCDIFADDR may be defined on linux despite the fact that
73  * it doesn't work. */
74 #if !defined(SIOCDIFADDR) && defined(SIOCATALKDIFADDR)
75 #define SIOCDIFADDR SIOCATALKDIFADDR
76 #endif
77
78 #define elements(a)     (sizeof(a)/sizeof((a)[0]))
79
80 #define PKTSZ   1024
81
82 extern int      rtmp_packet();
83 extern int      nbp_packet();
84 extern int      aep_packet();
85 extern int      zip_packet();
86
87 int             rtfd;
88
89 struct atserv   atserv[] = {
90     { "rtmp",           1,      rtmp_packet },          /* 0 */
91     { "nbp",            2,      nbp_packet },           /* 1 */
92     { "echo",           4,      aep_packet },           /* 2 */
93     { "zip",            6,      zip_packet },           /* 3 */
94 };
95 int             atservNATSERV = elements( atserv );
96
97 struct interface        *interfaces = NULL, *ciface = NULL;
98
99 int             debug = 0, quiet = 0, chatty = 0;
100 char            *configfile = NULL;
101 int             ziptimeout = 0, transition = 0;
102 int             stabletimer, stable = 0, newrtmpdata = 0, noparent = 0;
103 static int      ninterfaces;
104 int             defphase = IFACE_PHASE2;
105 int             nfds = 0;
106 fd_set          fds;
107 char            Packet[ PKTSZ ];
108 char            *version = VERSION;
109 static char     *pidfile = _PATH_ATALKDLOCK;
110
111
112 /* from config.c */
113
114 int readconf( char * );
115 int getifconf( void );
116 int writeconf( char * );
117
118 /* this is the messiest of the bunch as atalkd can exit pretty much
119  * everywhere. we delete interfaces here instead of in as_down. */
120 static void atalkd_exit(const int i)
121 {
122 #ifdef SIOCDIFADDR
123   struct interface *iface;
124
125   for (iface = interfaces; iface; iface = iface->i_next) {
126     if (ifconfig( iface->i_name, SIOCDIFADDR, &iface->i_addr)) {
127 #ifdef SIOCATALKDIFADDR
128 #if (SIOCDIFADDR != SIOCATALKDIFADDR)
129       if (!ifconfig(iface->i_name, SIOCATALKDIFADDR, &iface->i_addr)) 
130         continue;
131 #endif
132 #endif
133       syslog( LOG_ERR, "difaddr(%u.%u): %m", 
134               ntohs(iface->i_addr.sat_addr.s_net), 
135               iface->i_addr.sat_addr.s_node);
136     }
137   }
138 #endif 
139
140   server_unlock(pidfile);
141   exit(i);
142 }
143
144
145 #if !defined( ibm032 ) && !defined( _IBMR2 )
146     void
147 #endif ibm032 _IBMR2
148 as_timer()
149 {
150     struct sockaddr_at  sat;
151     struct ziphdr       zh;
152     struct rtmp_head    rh;
153     struct rtmp_tuple   rt;
154     struct atport       *ap, *zap, *rap;
155     struct interface    *iface, *iface2;
156     struct gate         *gate, *fgate = NULL;
157     struct rtmptab      *rtmp, *frtmp;
158     struct ziptab       *zt;
159     char                *data, *end, packet[ ATP_BUFSIZ ];
160     int                 sentzipq = 0;
161     int                 n, cc;
162
163     memset(&sat, 0, sizeof( struct sockaddr_at ));
164     for ( iface = interfaces; iface; iface = iface->i_next ) {
165         if ( iface->i_flags & IFACE_LOOPBACK ) {
166             continue;
167         }
168         for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
169             if ( ap->ap_packet == zip_packet ) {
170                 zap = ap;
171             }
172             if ( ap->ap_packet == rtmp_packet ) {
173                 rap = ap;
174             }
175         }
176
177         if (( iface->i_flags & ( IFACE_ADDR|IFACE_CONFIG|IFACE_NOROUTER )) ==
178                 IFACE_ADDR ) {
179             if ( iface->i_time < 3 ) {
180                 if ( iface->i_flags & IFACE_PHASE1 ) {
181                   if (rtmp_request( iface ) < 0) {
182                       syslog(LOG_ERR, "rtmp_request: %m");
183                       atalkd_exit(1);
184                   }
185                     newrtmpdata = 1;
186                 } else {
187                   if (zip_getnetinfo( iface ) < 0) {
188                     syslog(LOG_ERR, "zip_getnetinfo: %m");
189                     atalkd_exit(1);
190                   }
191                   sentzipq = 1;
192                 }
193                 iface->i_time++;
194             } else {
195                 iface->i_flags |= IFACE_NOROUTER;
196                 if ((iface->i_flags & IFACE_ISROUTER)) {
197                     if (( iface->i_flags & IFACE_SEED ) == 0 ) {
198                         /*
199                          * No seed info, and we've got multiple interfaces.
200                          * Wait forever.
201                          */
202                         syslog( LOG_INFO,
203                                 "as_timer multiple interfaces, no seed" );
204                         syslog( LOG_INFO, "as_timer can't configure %s",
205                                 iface->i_name );
206                         syslog( LOG_INFO, "as_timer waiting for router" );
207                         iface->i_time = 0;
208                         continue;
209                     } else {
210                         /*
211                          * Complete configuration for iface, and boot next
212                          * interface.
213                          */
214                         iface->i_flags |= IFACE_CONFIG;
215                         for ( zt = iface->i_czt; zt; zt = zt->zt_next ) {
216                             if (addzone( iface->i_rt, zt->zt_len, 
217                                          zt->zt_name) < 0) {
218                               syslog(LOG_ERR, "addzone: %m");
219                               atalkd_exit(1);
220                             }
221                         }
222                         if ( iface->i_rt->rt_zt ) {
223                             iface->i_rt->rt_flags &= ~RTMPTAB_ZIPQUERY;
224                             iface->i_rt->rt_flags |= RTMPTAB_HASZONES;
225                         }
226                         if ( iface->i_flags & IFACE_PHASE1 ) {
227                             syslog( LOG_INFO,
228                                     "as_timer configured %s phase 1 from seed",
229                                     iface->i_name );
230                             setaddr( iface, IFACE_PHASE1,
231                                     iface->i_caddr.sat_addr.s_net,
232                                     iface->i_addr.sat_addr.s_node,
233                                     iface->i_caddr.sat_addr.s_net,
234                                     iface->i_caddr.sat_addr.s_net );
235                         } else {
236                             syslog( LOG_INFO,
237                                     "as_timer configured %s phase 2 from seed",
238                                     iface->i_name );
239                         }
240
241                         if ( looproute( iface, RTMP_ADD )) { /* -1 or 1 */
242                             syslog( LOG_ERR,
243                                     "as_timer: can't route %u.%u to loop: %m",
244                                     ntohs( iface->i_addr.sat_addr.s_net ),
245                                     iface->i_addr.sat_addr.s_node );
246                             atalkd_exit( 1 );
247                         }
248                         if ( iface == ciface ) {
249                             ciface = ciface->i_next;
250                             bootaddr( ciface );
251                         }
252                     }
253                 } else {
254                     /*
255                      * Configure for no router operation.  Wait for a route
256                      * to become available in rtmp_packet().
257                      */
258                     syslog( LOG_INFO, "config for no router" );
259                       
260                     if ( iface->i_flags & IFACE_PHASE2 ) {
261                         iface->i_rt->rt_firstnet = 0;
262                         iface->i_rt->rt_lastnet = htons( STARTUP_LASTNET );
263                         setaddr( iface, IFACE_PHASE2,
264                                 iface->i_addr.sat_addr.s_net,
265                                 iface->i_addr.sat_addr.s_node,
266                                 0, htons( STARTUP_LASTNET ));
267                     }
268                     if ( looproute( iface, RTMP_ADD ) ) { /* -1 or 1 */
269                         syslog( LOG_ERR,
270                                 "as_timer: can't route %u.%u to loopback: %m",
271                                 ntohs( iface->i_addr.sat_addr.s_net ),
272                                 iface->i_addr.sat_addr.s_node );
273                         atalkd_exit( 1 );
274                     }
275
276                     if ( iface == ciface ) {
277                       ciface = ciface->i_next;
278                       bootaddr( ciface );
279                     }
280                 }
281             }
282         }
283
284         for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
285             if ( fgate ) {
286                 free( (caddr_t)fgate );
287                 fgate = NULL;
288             }
289
290             n = 0;
291             data = packet + 1 + sizeof( struct ziphdr );
292             end = packet + sizeof( packet );
293
294             sat = gate->g_sat;
295             sat.sat_port = zap->ap_port;
296
297             /*
298              * Perform timeouts on routers.  If we've only got one
299              * interface, we'll use these timeouts to decide that
300              * our zone has gone away.
301              */
302             if ( ++gate->g_state >= RTMPTAB_BAD ) {
303                 syslog( LOG_INFO, "as_timer gateway %u.%u down",
304                         ntohs( gate->g_sat.sat_addr.s_net ),
305                         gate->g_sat.sat_addr.s_node );
306                 rtmp = gate->g_rt;
307                 while ( rtmp ) {
308                     frtmp = rtmp->rt_next;
309                     if ( rtmp->rt_hops == RTMPHOPS_POISON ||
310                             rtmp->rt_iprev == 0 ) {
311                         rtmp_free( rtmp );
312                     } else {
313                         rtmp->rt_hops = RTMPHOPS_POISON;
314                         if ((cc = rtmp_replace( rtmp )) < 0) {
315                           syslog(LOG_ERR, "rtmp_replace: %m");
316                           atalkd_exit(1);
317                         }
318                         if (cc) {
319                             gate->g_state = rtmp->rt_state = RTMPTAB_GOOD;
320                         }
321                     }
322                     rtmp = frtmp;
323                 }
324                 if ( gate->g_rt == 0 ) {
325                     if ( gate->g_prev == 0 ) {
326                         gate->g_iface->i_gate = gate->g_next;
327                     } else {
328                         gate->g_prev->g_next = gate->g_next;
329                     }
330                     if ( gate->g_next != 0 ) {
331                         gate->g_next->g_prev = gate->g_prev;
332                     }
333                     fgate = gate;       /* can't free here, just mark it */
334                 }
335                 /*
336                  * If this is the last router on the only interface,
337                  * reconfigure our netrange.  By marking the interface
338                  * as having no router, we will notice when a router
339                  * comes back up.
340                  *
341                  * XXX: actually, we always reconfigure an interface
342                  * if we're not a seed router.
343                  */
344
345                 if ( gate->g_iface->i_gate == 0 && 
346                      ((iface->i_flags & IFACE_SEED) == 0)) {
347                     gate->g_iface->i_flags |= IFACE_NOROUTER;
348                     gate->g_iface->i_flags &= ~IFACE_CONFIG;
349
350                     /* get rid of any zones associated with this iface */
351                     if (gate->g_iface->i_rt->rt_zt) {
352                       rtmp_delzonemap(gate->g_iface->i_rt);
353                       gate->g_iface->i_rt->rt_flags &= ~RTMPTAB_HASZONES;
354                     }
355
356                     syslog( LOG_INFO, "as_timer last gateway down" );
357
358                     /* Set netrange to 0-fffe.  */
359                     if ( gate->g_iface->i_flags & IFACE_PHASE2 ) {
360                         gate->g_iface->i_rt->rt_firstnet = 0;
361                         gate->g_iface->i_rt->rt_lastnet =
362                                 htons( STARTUP_LASTNET );
363                         setaddr( iface, IFACE_PHASE2,
364                                 iface->i_addr.sat_addr.s_net,
365                                 iface->i_addr.sat_addr.s_node,
366                                 0, htons( STARTUP_LASTNET ));
367                     }
368                 }
369                 continue;
370             }
371
372             /*
373              * If we don't have a zone for our interface yet, ask for
374              * it from any router (all routers) on the interface.
375              */
376             if (( iface->i_rt->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
377                 iface->i_rt->rt_flags |= RTMPTAB_ZIPQUERY;
378                 memcpy( data, &iface->i_rt->rt_firstnet, sizeof( u_short ));
379                 data += sizeof( u_short );
380                 n++;
381             }
382
383             rtmp = gate->g_rt;
384             while ( rtmp ) {
385                 /*
386                  * Delete old routing tuples.
387                  */
388                 if ( rtmp->rt_state != RTMPTAB_PERM ) {
389                     rtmp->rt_state++;
390                 }
391
392                 /*
393                  * We've not been updated for this route in a while.  If
394                  * it's not in use, go ahead and remove it.  If it is in
395                  * use, mark the route as down (POISON), and look for a
396                  * better route.  If one is found, delete this route and use
397                  * the new one.  If it's not found, mark the route as GOOD
398                  * (so we'll propogate our poison) and delete it the next
399                  * time it becomes BAD.
400                  */
401                 if ( rtmp->rt_state >= RTMPTAB_BAD ) {
402                     frtmp = rtmp->rt_next;
403                     if ( rtmp->rt_iprev == 0 ) {        /* not in use */
404                         rtmp_free( rtmp );
405                     } else {                            /* in use */
406                         if ( rtmp->rt_hops == RTMPHOPS_POISON ) {
407                             rtmp_free( rtmp );
408                         } else {
409                             rtmp->rt_hops = RTMPHOPS_POISON;
410                             if ((cc = rtmp_replace( rtmp )) < 0) {
411                                 syslog(LOG_ERR, "rtmp_replace: %m");
412                                 atalkd_exit(1);
413                             }
414                             if (cc)
415                                 rtmp->rt_state = RTMPTAB_GOOD;
416                         }
417                     }
418                     rtmp = frtmp;
419                     continue;
420                 }
421
422                 /*
423                  * Do ZIP lookups.
424                  */
425                 if ( rtmp->rt_iprev &&
426                         ( rtmp->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
427                     if ( data + sizeof( u_short ) > end || n == 255 ) {
428                         /* send what we've got */
429                         zh.zh_op = ZIPOP_QUERY;
430                         zh.zh_count = n;
431                         cc = data - packet;
432                         data = packet;
433                         *data++ = DDPTYPE_ZIP;
434                         memcpy( data, &zh, sizeof( struct ziphdr ));
435
436                         if ( sendto( zap->ap_fd, packet, cc, 0,
437                                 (struct sockaddr *)&sat,
438                                 sizeof( struct sockaddr_at )) < 0 ) {
439                             syslog( LOG_ERR, "as_timer sendto: %m" );
440                         }
441                         sentzipq = 1;
442
443                         n = 0;
444                         data = packet + 1 + sizeof( struct ziphdr );
445                         end = packet + sizeof( packet );
446                     }
447
448                     /*
449                      * rt_nzq is number of ZIP Queries we've issued for a
450                      * given netrange.  If we've got ziptimeout on, we
451                      * will only ask 3 times for any given netrange.
452                      * Interestingly enough, since rt_nzq is a u_char,
453                      * it will overflow after a while.  This means we will
454                      * periodically ask for nets that we've decided not to
455                      * ask about, and warn that we can't get it's zone.
456                      */
457                     if ( rtmp->rt_nzq++ == 3 ) {
458                         syslog( LOG_INFO, "as_timer can't get zone for %u",
459                                 ntohs( rtmp->rt_firstnet ));
460                     }
461                     if ( rtmp->rt_nzq > 3 ) {
462                         if ( ziptimeout ) {
463                             rtmp = rtmp->rt_next;
464                             continue;
465                         }
466                     } else {
467                         sentzipq = 1;
468                     }
469                     rtmp->rt_flags |= RTMPTAB_ZIPQUERY;
470                     memcpy( data, &rtmp->rt_firstnet, sizeof( u_short ));
471                     data += sizeof( u_short );
472                     n++;
473                 }
474                 rtmp = rtmp->rt_next;
475             }
476
477             /* send what we've got */
478             if ( n > 0 ) {
479                 zh.zh_op = ZIPOP_QUERY;
480                 zh.zh_count = n;
481                 cc = data - packet;
482                 data = packet;
483                 *data++ = DDPTYPE_ZIP;
484                 memcpy( data, &zh, sizeof( struct ziphdr ));
485
486                 if ( sendto( zap->ap_fd, packet, cc, 0, (struct sockaddr *)&sat,
487                         sizeof( struct sockaddr_at )) < 0 ) {
488                     syslog( LOG_ERR, "as_timer sendto: %m" );
489                 }
490             }
491         }
492         if ( fgate ) {
493             free( (caddr_t)fgate );
494             fgate = NULL;
495         }
496
497         /*
498          * Send RTMP broadcasts if we have multiple interfaces or our 
499          * interface is configured as a router.  
500          */
501         if ((iface->i_flags & IFACE_ISROUTER)) {
502 #ifdef BSD4_4
503             sat.sat_len = sizeof( struct sockaddr_at );
504 #endif BSD4_4
505             sat.sat_family = AF_APPLETALK;
506             sat.sat_addr.s_net = ATADDR_ANYNET;
507             sat.sat_addr.s_node = ATADDR_BCAST;
508             sat.sat_port = rap->ap_port;
509
510             data = packet;
511             end = data + sizeof( packet );
512             *data++ = DDPTYPE_RTMPRD;
513             rh.rh_net = iface->i_addr.sat_addr.s_net;
514             rh.rh_nodelen = 8;
515             rh.rh_node = iface->i_addr.sat_addr.s_node;
516             memcpy( data, &rh, sizeof( struct rtmp_head ));
517             data += sizeof( struct rtmp_head );
518             n = 0;
519
520
521             if ( iface->i_flags & IFACE_PHASE1 ) {
522                 rt.rt_net = 0;
523                 rt.rt_dist = 0x82;
524                 memcpy( data, &rt, SZ_RTMPTUPLE );
525                 data += SZ_RTMPTUPLE;
526             } else {
527                 rt.rt_net = iface->i_rt->rt_firstnet;
528                 rt.rt_dist = 0x80;
529                 memcpy( data, &rt, SZ_RTMPTUPLE );
530                 data += SZ_RTMPTUPLE;
531
532                 rt.rt_net = iface->i_rt->rt_lastnet;
533                 rt.rt_dist = 0x82;
534                 memcpy( data, &rt, SZ_RTMPTUPLE );
535                 data += SZ_RTMPTUPLE;
536             }
537
538             for ( iface2 = interfaces; iface2; iface2 = iface2->i_next ) {
539
540               /* XXX: there used to be a bit checking against iface ==
541                  iface2. also, we don't want to send an rtmp broadcast
542                  to an interface that doesn't want it.  */
543                 if ((( iface2->i_flags & IFACE_CONFIG ) == 0) ||
544                     ((iface2->i_flags & IFACE_ISROUTER) == 0)) {
545                     continue;
546                 }
547                 /*
548                  * Fill in tuples.  Always send the same thing, regardless
549                  * of the phase of the destination.  Routers who don't
550                  * understand extended rtmp packets will toss extended
551                  * tuples because their distance will have the high bit set.
552                  */
553                 for ( rtmp = iface2->i_rt; rtmp; rtmp = rtmp->rt_inext ) {
554                     /* don't broadcast routes we have no zone for */
555                     if ( rtmp->rt_zt == 0 ||
556                             ( rtmp->rt_flags & RTMPTAB_ZIPQUERY ) ||
557                             ( rtmp->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
558                         continue;
559                     }
560
561                     if ((( rtmp->rt_flags & RTMPTAB_EXTENDED ) &&
562                             data + 2 * SZ_RTMPTUPLE > end ) ||
563                             data + SZ_RTMPTUPLE > end ) {
564                         if ( sendto( rap->ap_fd, packet, data - packet, 0,
565                                 (struct sockaddr *)&sat,
566                                 sizeof( struct sockaddr_at )) < 0 ) {
567                             syslog( LOG_ERR, "as_timer sendto %u.%u (%u): %m",
568                                     ntohs( sat.sat_addr.s_net ),
569                                     sat.sat_addr.s_node,
570                                     ntohs( iface->i_rt->rt_firstnet ));
571                         }
572
573                         if ( iface->i_flags & IFACE_PHASE2 ) {
574                             data = packet + 1 + sizeof( struct rtmp_head ) +
575                                     2 * SZ_RTMPTUPLE;
576                         } else {
577                             data = packet + 1 + sizeof( struct rtmp_head ) +
578                                     SZ_RTMPTUPLE;
579                         }
580                         n = 0;
581                     }
582
583                     rt.rt_net = rtmp->rt_firstnet;
584                     rt.rt_dist = rtmp->rt_hops;
585                     if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
586                         rt.rt_dist |= 0x80;
587                     }
588                     memcpy( data, &rt, SZ_RTMPTUPLE );
589                     data += SZ_RTMPTUPLE;
590
591                     if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
592                         rt.rt_net = rtmp->rt_lastnet;
593                         rt.rt_dist = 0x82;
594                         memcpy( data, &rt, SZ_RTMPTUPLE );
595                         data += SZ_RTMPTUPLE;
596                     }
597                     n++;
598                 }
599             }
600
601             /* send rest */
602             if ( n ) {
603                 if ( sendto( rap->ap_fd, packet, data - packet, 0,
604                         (struct sockaddr *)&sat,
605                         sizeof( struct sockaddr_at )) < 0 ) {
606                     syslog( LOG_ERR, "as_timer sendto %u.%u (%u): %m",
607                             ntohs( sat.sat_addr.s_net ),
608                             sat.sat_addr.s_node,
609                             ntohs( iface->i_rt->rt_firstnet ));
610                 }
611             }
612         }
613     }
614
615     /*
616      * Check if we're stable.  Each time we configure an interface, we
617      * sent stabletimer to UNSTABLE.  If stabletimer ever gets to
618      * STABLEANYWAY, we give up and decide to "be" stable anyway.
619      * Normally, we wait for stabletimer get <= STABLE with no new rtmp
620      * data and all zip data complete.
621      */
622     if ( !stable ) {
623         if ( stabletimer <= STABLE && !newrtmpdata && !sentzipq ) {
624             /* write out config file */
625             stable = 1;
626             writeconf( configfile );
627         } else {
628             if ( stabletimer-- <= STABLEANYWAY ) {
629                 stable = 1;
630             }
631         }
632         newrtmpdata = 0;
633
634         if ( stable && !noparent ) {
635             noparent = 1;
636             syslog( LOG_INFO, "ready %d/%d/%d", stabletimer, newrtmpdata,
637                     sentzipq );
638             if ( !debug ) {
639                 /*
640                  * Seems like we could get here more than once...
641                  */
642                 if ( kill( getpid(), SIGSTOP ) < 0 ) {
643                     syslog( LOG_ERR, "as_timer: kill-self failed!" );
644                     atalkd_exit( 1 );
645                 }
646             }
647         }
648     }
649
650 #ifdef DEBUG
651     consistency();
652 #endif DEBUG
653 }
654
655 #ifdef DEBUG
656 /*
657 * Consistency check...
658 */
659 consistency()
660 {
661     struct rtmptab      *rtmp;
662     struct list         *lr, *lz;
663     struct ziptab       *zt;
664
665     for ( zt = ziptab; zt; zt = zt->zt_next ) {
666         for ( lr = zt->zt_rt; lr; lr = lr->l_next ) {
667             rtmp = (struct rtmptab *)lr->l_data;
668             if ( rtmp->rt_iprev == 0 && rtmp->rt_gate != 0 ) {
669                 syslog( LOG_ERR, "%.*s has %u-%u (unused)\n",
670                         zt->zt_len, zt->zt_name, ntohs( rtmp->rt_firstnet ),
671                         ntohs( rtmp->rt_lastnet ));
672                 atalkd_exit(1);
673             }
674             for ( lz = rtmp->rt_zt; lz; lz = lz->l_next ) {
675                 if ( zt == (struct ziptab *)lz->l_data ) {
676                     break;
677                 }
678             }
679             if ( lz == 0 ) {
680                 syslog( LOG_ERR, "no map from %u-%u to %.*s\n", 
681                         ntohs( rtmp->rt_firstnet ),
682                         ntohs( rtmp->rt_lastnet ),
683                         zt->zt_len, zt->zt_name );
684                 atalkd_exit(1);
685             }
686         }
687     }
688 }
689 #endif DEBUG
690
691 #if !defined( ibm032 ) && !defined( _IBMR2 )
692     void
693 #endif ibm032 _IBMR2
694 as_debug()
695 {
696     struct interface    *iface;
697     struct list         *l;
698     struct ziptab       *zt;
699     struct gate         *gate;
700     struct rtmptab      *rt;
701     FILE                *rtmpdebug;
702
703     if (( rtmpdebug = fopen( _PATH_ATALKDEBUG, "w" )) == NULL ) {
704         syslog( LOG_ERR, "rtmp: %m" );
705     }
706
707     for ( iface = interfaces; iface; iface = iface->i_next ) {
708         fprintf( rtmpdebug, "interface %s %u.%u ", iface->i_name,
709                 ntohs( iface->i_addr.sat_addr.s_net ),
710                 iface->i_addr.sat_addr.s_node );
711         if ( iface->i_flags & IFACE_PHASE1 ) {
712             putc( '1', rtmpdebug );
713         }
714         if ( iface->i_flags & IFACE_PHASE2 ) {
715             putc( '2', rtmpdebug );
716         }
717         if ( iface->i_flags & IFACE_RSEED ) {
718             putc( 'R', rtmpdebug );
719         }
720         if ( iface->i_flags & IFACE_SEED ) {
721             putc( 'S', rtmpdebug );
722         }
723         if ( iface->i_flags & IFACE_DONTROUTE ) {
724             putc( 'D', rtmpdebug );
725         }
726         if ( iface->i_flags & IFACE_ADDR ) {
727             putc( 'A', rtmpdebug );
728         }
729         if ( iface->i_flags & IFACE_CONFIG ) {
730             putc( 'C', rtmpdebug );
731         }
732         if ( iface->i_flags & IFACE_NOROUTER ) {
733             putc( 'N', rtmpdebug );
734         }
735         if ( iface->i_flags & IFACE_LOOP ) {
736             putc( 'L', rtmpdebug );
737         }
738         putc( '\n', rtmpdebug );
739
740         if ( iface->i_rt ) {
741             fprintf( rtmpdebug, "\t%u-%u ",
742                     ntohs( iface->i_rt->rt_firstnet ),
743                     ntohs( iface->i_rt->rt_lastnet ));
744             if ( iface->i_rt->rt_flags & RTMPTAB_ZIPQUERY ) {
745                 putc( 'q', rtmpdebug );
746             }
747             if ( iface->i_rt->rt_flags & RTMPTAB_HASZONES ) {
748                 putc( 'z', rtmpdebug );
749             }
750             if ( iface->i_rt->rt_flags & RTMPTAB_EXTENDED ) {
751                 putc( 'x', rtmpdebug );
752             }
753             putc( 'i', rtmpdebug );
754             for ( l = iface->i_rt->rt_zt; l; l = l->l_next ) {
755                 zt = (struct ziptab *)l->l_data;
756                 fprintf( rtmpdebug, " '%.*s'", zt->zt_len, zt->zt_name );
757             }
758             fprintf( rtmpdebug, "\n" );
759         }
760
761         for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
762             fprintf( rtmpdebug, "gate %u.%u %X\n",
763                     ntohs( gate->g_sat.sat_addr.s_net ),
764                     gate->g_sat.sat_addr.s_node, gate->g_state );
765             for ( rt = gate->g_rt; rt; rt = rt->rt_next ) {
766                 fprintf( rtmpdebug, "\t%u-%u ", ntohs( rt->rt_firstnet ),
767                         ntohs( rt->rt_lastnet ));
768                 if ( rt->rt_flags & RTMPTAB_ZIPQUERY ) {
769                     putc( 'q', rtmpdebug );
770                 }
771                 if ( rt->rt_flags & RTMPTAB_HASZONES ) {
772                     putc( 'z', rtmpdebug );
773                 }
774                 if ( rt->rt_flags & RTMPTAB_EXTENDED ) {
775                     putc( 'x', rtmpdebug );
776                 }
777                 if ( rt->rt_iprev ) {
778                     putc( 'i', rtmpdebug );
779                 }
780                 for ( l = rt->rt_zt; l; l = l->l_next ) {
781                     zt = (struct ziptab *)l->l_data;
782                     fprintf( rtmpdebug, " '%.*s'", zt->zt_len, zt->zt_name );
783                 }
784                 fprintf( rtmpdebug, "\n" );
785             }
786         }
787     }
788
789     fclose( rtmpdebug );
790 }
791
792 /*
793  * Called when SIGTERM is recieved.  Remove all routes and then exit.
794  */
795 #if !defined( ibm032 ) && !defined( _IBMR2 )
796     void
797 #endif ibm032 _IBMR2
798 as_down()
799 {
800     struct interface    *iface;
801     struct gate         *gate;
802     struct rtmptab      *rt;
803
804     for ( iface = interfaces; iface; iface = iface->i_next ) {
805         for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
806             for ( rt = gate->g_rt; rt; rt = rt->rt_next ) {
807                 if ( rt->rt_iprev ) {
808                     if ( gateroute( RTMP_DEL, rt ) < 0 ) {
809                         syslog( LOG_ERR, "as_down remove %u-%u failed: %m",
810                                 ntohs( rt->rt_firstnet ),
811                                 ntohs( rt->rt_lastnet ));
812                     }
813                 }
814             }
815         }
816         if ( iface->i_flags & IFACE_LOOP ) {
817           if (looproute( iface, RTMP_DEL )) {
818             syslog( LOG_ERR, "as_down remove %s %u.%u failed: %m",
819                     iface->i_name, ntohs( iface->i_addr.sat_addr.s_net ),
820                     iface->i_addr.sat_addr.s_node );
821           }
822         }
823     }
824
825     syslog( LOG_INFO, "done" );
826     atalkd_exit( 0 );
827 }
828
829 int main( ac, av )
830     int         ac;
831     char        **av;
832 {
833     extern char         *optarg;
834     extern int          optind;
835
836     struct sockaddr_at  sat;
837     struct sigaction    sv;
838     struct itimerval    it;
839     struct interface    *iface;
840     int                 status;
841     struct atport       *ap;
842     fd_set              readfds;
843     int                 i, mask, c;
844     SOCKLEN_T           fromlen;
845     char                *prog;
846 ;
847
848     while (( c = getopt( ac, av, "12qsdtf:P:" )) != EOF ) {
849         switch ( c ) {
850         case '1' :
851             defphase = IFACE_PHASE1;
852             break;
853
854         case '2' :
855             defphase = IFACE_PHASE2;
856             break;
857
858         case 'd' :
859             debug++;
860             break;
861
862         case 'f' :
863             configfile = optarg;
864             break;
865
866         case 'q' :      /* don't seed */
867             quiet++;
868             break;
869
870         case 's' :      /* seed */
871             chatty++;
872             break;
873
874         case 't' :      /* transition */
875             transition++;
876             break;
877
878         case 'P' :      /* pid file */
879             pidfile = optarg;
880             break;
881
882         default :
883             fprintf( stderr, "Unknown option -- '%c'\n", c );
884             exit( 1 );
885         }
886     }
887     if ( optind != ac ) {
888         fprintf( stderr, "Too many arguments.\n" );
889         exit( 1 );
890     }
891
892     if (( prog = strrchr( av[ 0 ], '/' )) == NULL ) {
893         prog = av[ 0 ];
894     } else {
895         prog++;
896     }
897
898     /*
899      * Configure loop back address first, so appearances of "lo0" in
900      * the config file fail.  Also insures that lo0 gets configured,
901      * even if there's some hangup during configuration of some
902      * other interface.
903      */
904     if (( interfaces = newiface( LOOPIFACE )) == NULL ) {
905         perror( "newiface" );
906         exit( 1 );
907     }
908     interfaces->i_flags |= IFACE_PHASE2 | IFACE_LOOPBACK;
909
910     /*
911      * Check our initial configuration before we fork. This way we can
912      * complain about syntax errors on stdout.
913      *
914      * Basically, if we're going to read our config file, we should read
915      * it and initialize our data structures. If we're not going to read
916      * our config file, use GIFCONF to initialize our data structures.
917      */
918     if ( readconf( configfile ) < 0 && getifconf() < 0 ) {
919         fprintf( stderr, "%s: can't get interfaces, exiting.\n", prog );
920         exit( 1 );
921     }
922
923     /* we need to count up our interfaces so that we can simplify things
924      * later. we also need to figure out if we have more than one interface
925      * that is routing. */
926     for (i = 0, ninterfaces = 0, iface = interfaces; iface;
927          iface=iface->i_next) {
928       if (iface->i_flags & IFACE_DONTROUTE)
929         i++;
930       ninterfaces++;
931     }
932     i = ninterfaces - i; /* number of routable interfaces */
933
934     /*
935      * At this point, we have (at least partially) initialized data
936      * structures. Fill in what we can and verify that nothing is obviously
937      * broken.
938      */
939     for (iface = interfaces; iface; iface = iface->i_next) {
940         /* Apply the default phase */
941         if (( iface->i_flags & IFACE_PHASE1 ) == 0 &&
942                 ( iface->i_flags & IFACE_PHASE2 ) == 0 ) {
943             iface->i_flags |= defphase;
944         }
945
946         /* set up router flag information. if we have multiple interfaces
947          * and DONTROUTE isn't set, set up ROUTER. i is the number of 
948          * interfaces that don't have the DONTROUTE flag set. */
949         if ((i > IFBASE) && ((iface->i_flags & IFACE_DONTROUTE) == 0)) {
950           iface->i_flags |= IFACE_ISROUTER;
951         }
952
953         /* Set default addresses */
954         if ( iface->i_rt == NULL ) {
955             if (( iface->i_rt = newrt(iface)) == NULL ) {
956                 perror( "newrt" );
957                 exit( 1 );
958             }
959
960             if ( iface->i_flags & IFACE_PHASE1 ) {
961                 iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet =
962                         iface->i_caddr.sat_addr.s_net;
963             } else {
964                 if ( iface->i_caddr.sat_addr.s_net != ATADDR_ANYNET ||
965                         ( iface->i_flags & IFACE_LOOPBACK )) {
966                     iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet =
967                             iface->i_caddr.sat_addr.s_net;
968                 } else {
969                     iface->i_rt->rt_firstnet = htons( STARTUP_FIRSTNET );
970                     iface->i_rt->rt_lastnet = htons( STARTUP_LASTNET );
971                 }
972             }
973         }
974         
975         if (( iface->i_flags & IFACE_PHASE1 ) == 0 ) {
976             iface->i_rt->rt_flags |= RTMPTAB_EXTENDED;
977         }
978
979         if ( iface->i_caddr.sat_addr.s_net == ATADDR_ANYNET ) {
980             iface->i_caddr.sat_addr.s_net = iface->i_rt->rt_firstnet;
981         }
982
983         if ( debug ) {
984             dumpconfig( iface );        /* probably needs args */
985         }
986     }
987
988     /*
989      * A little consistency check...
990      */
991     if ( ninterfaces < IFBASE ) {
992         fprintf( stderr, "%s: zero interfaces, exiting.\n", prog );
993         exit( 1 );
994     }
995
996     /* do this here so that we can use ifconfig */
997 #ifdef __svr4__
998     if ( plumb() < 0 ) {
999         fprintf(stderr, "can't establish STREAMS plumbing, exiting.\n" );
1000         atalkd_exit( 1 );
1001     }
1002 #endif __svr4__
1003
1004     /* delete pre-existing interface addresses. */
1005 #ifdef SIOCDIFADDR
1006     for (iface = interfaces; iface; iface = iface->i_next) {
1007       if (ifconfig(iface->i_name, SIOCDIFADDR, &iface->i_addr)) {
1008 #ifdef SIOCATALKDIFADDR
1009 #if (SIOCDIFADDR != SIOCATALKDIFADDR)
1010         ifconfig(iface->i_name, SIOCATALKDIFADDR, &iface->i_addr);
1011 #endif
1012 #endif
1013       }
1014     }
1015 #endif
1016
1017     /*
1018      * Disassociate. The child will send itself a signal when it is
1019      * stable. This indicates that other processes may begin using
1020      * AppleTalk.
1021      */
1022     switch (i = server_lock("atalkd", pidfile, debug)) {
1023     case -1:
1024       exit(1);
1025     case 0: /* child */
1026       break;
1027     default: /* parent */
1028       /*
1029        * Wait for the child to send itself a SIGSTOP, after which
1030        * we send it a SIGCONT and exit ourself.
1031        */
1032       if ( wait3( &status, WUNTRACED, (struct rusage *)0 ) != i) {
1033         perror( "wait3" );      /* Child died? */
1034         atalkd_exit( 1 );
1035       }
1036       if ( !WIFSTOPPED( status )) {
1037         fprintf( stderr, "AppleTalk not up! Check your syslog for the reason." );
1038         if ( WIFEXITED( status )) {
1039           fprintf( stderr, " Child exited with %d.\n",
1040                    WEXITSTATUS( status ));
1041         } else {
1042           fprintf( stderr, " Child died.\n" );
1043         }
1044         atalkd_exit( 1 );
1045       }
1046       if ( kill(i, SIGCONT ) < 0 ) {
1047         perror( "kill" );
1048         atalkd_exit( 1 );
1049       }
1050       exit( 0 );
1051     }
1052
1053 #ifdef ultrix
1054     openlog( prog, LOG_PID );
1055 #else ultrix
1056     openlog( prog, LOG_PID, LOG_DAEMON );
1057 #endif ultrix
1058
1059     syslog( LOG_INFO, "restart (%s)", version );
1060
1061     /*
1062      * Socket for use in routing ioctl()s. Can't add routes to our
1063      * interfaces until we have our routing socket.
1064      */
1065 #ifdef BSD4_4
1066     if (( rtfd = socket( PF_ROUTE, SOCK_RAW, AF_APPLETALK )) < 0 ) {
1067         syslog( LOG_ERR, "route socket: %m" );
1068         atalkd_exit( 1 );
1069     }
1070     if ( shutdown( rtfd, 0 ) < 0 ) {
1071         syslog( LOG_ERR, "route shutdown: %m" );
1072         atalkd_exit( 1 );
1073     }
1074 #else BSD4_4
1075     if (( rtfd = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1076         syslog( LOG_ERR, "route socket: %m" );
1077         atalkd_exit( 1 );
1078     }
1079 #endif BSD4_4
1080
1081     memset(&sv, 0, sizeof(sv));
1082     sv.sa_handler = as_down;
1083     sigemptyset( &sv.sa_mask );
1084     sigaddset( &sv.sa_mask, SIGUSR1 );
1085     sigaddset( &sv.sa_mask, SIGALRM );
1086     sigaddset( &sv.sa_mask, SIGTERM );
1087     sv.sa_flags = SA_RESTART;
1088     if ( sigaction( SIGTERM, &sv, NULL) < 0 ) {
1089         syslog( LOG_ERR, "sigterm: %m" );
1090         atalkd_exit( 1 );
1091     }
1092
1093     sv.sa_handler = as_debug;
1094     sigemptyset( &sv.sa_mask );
1095     sigaddset( &sv.sa_mask, SIGUSR1 );
1096     sigaddset( &sv.sa_mask, SIGALRM );
1097     sigaddset( &sv.sa_mask, SIGTERM );
1098     sv.sa_flags = SA_RESTART;
1099     if ( sigaction( SIGUSR1, &sv, NULL) < 0 ) {
1100         syslog( LOG_ERR, "sigusr1: %m" );
1101         atalkd_exit( 1 );
1102     }
1103
1104     sv.sa_handler = as_timer;
1105     sigemptyset( &sv.sa_mask );
1106     sigaddset( &sv.sa_mask, SIGUSR1 );
1107     sigaddset( &sv.sa_mask, SIGALRM );
1108     sigaddset( &sv.sa_mask, SIGTERM );
1109     sv.sa_flags = SA_RESTART;
1110     if ( sigaction( SIGALRM, &sv, NULL) < 0 ) {
1111         syslog( LOG_ERR, "sigalrm: %m" );
1112         atalkd_exit( 1 );
1113     }
1114
1115     it.it_interval.tv_sec = 10L;
1116     it.it_interval.tv_usec = 0L;
1117     it.it_value.tv_sec = 10L;
1118     it.it_value.tv_usec = 0L;
1119     if ( setitimer( ITIMER_REAL, &it, NULL) < 0 ) {
1120         syslog( LOG_ERR, "setitimer: %m" );
1121         atalkd_exit( 1 );
1122     }
1123
1124     ciface = interfaces;
1125     bootaddr( ciface );
1126     for (;;) {
1127         readfds = fds;
1128         if ( select( nfds, &readfds, NULL, NULL, NULL) < 0 ) {
1129             if ( errno == EINTR ) {
1130                 errno = 0;
1131                 continue;
1132             } else {
1133                 syslog( LOG_ERR, "select: %m" );
1134                 atalkd_exit( 1 );
1135             }
1136         }
1137
1138         for ( iface = interfaces; iface; iface = iface->i_next ) {
1139             for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1140                 if ( FD_ISSET( ap->ap_fd, &readfds )) {
1141                     if ( ap->ap_packet ) {
1142                         fromlen = sizeof( struct sockaddr_at );
1143                         if (( c = recvfrom( ap->ap_fd, Packet, sizeof( Packet ),
1144                                 0, (struct sockaddr *)&sat, &fromlen )) < 0 ) {
1145                             syslog( LOG_ERR, "recvfrom: %m" );
1146                             continue;
1147                         }
1148 #ifdef DEBUG
1149                         if ( debug ) {
1150                             printf( "packet from %u.%u on %s (%x) %d (%d)\n",
1151                                     ntohs( sat.sat_addr.s_net ),
1152                                     sat.sat_addr.s_node, iface->i_name,
1153                                     iface->i_flags, ap->ap_port, ap->ap_fd );
1154                             bprint( Packet, c );
1155                         }
1156 #endif DEBUG
1157 #ifdef __svr4__
1158                         if ( sighold( SIGALRM ) || sighold( SIGUSR1 )) {
1159                             syslog( LOG_ERR, "sighold: %m" );
1160                             atalkd_exit( 1 );
1161                         }
1162 #else __svr4__
1163                         mask = sigsetmask( sigmask( SIGALRM ) |
1164                                 sigmask( SIGUSR1 ));
1165 #endif __svr4__
1166                         if (( *ap->ap_packet )( ap, &sat, Packet, c ) < 0) {
1167                           syslog(LOG_ERR, "ap->ap_packet: %m");
1168                           atalkd_exit(1);
1169                         }
1170
1171 #ifdef DEBUG
1172                         consistency();
1173 #endif DEBUG
1174 #ifdef __svr4__
1175                         if ( sigrelse( SIGUSR1 ) || sigrelse( SIGALRM )) {
1176                             syslog( LOG_ERR, "sigrelse: %m" );
1177                             atalkd_exit( 1 );
1178                         }
1179 #else __svr4__
1180                         sigsetmask( mask );
1181 #endif __svr4__
1182                     }
1183                 }
1184             }
1185         }
1186     }
1187 }
1188
1189 /*
1190  * This code is called (from main(), as_timer(), zip_packet(),
1191  * and rtmp_packet()) to set the initial "bootstrapping" address
1192  * on an interface.
1193  */
1194 void bootaddr( iface )
1195     struct interface    *iface;
1196 {
1197     if ( iface == 0 ) {
1198         return;
1199     }
1200
1201     /* consistency */
1202     if ( iface->i_flags & IFACE_ADDR ) {
1203         syslog( LOG_ERR, "bootaddr OOPS!" );
1204         atalkd_exit(1);
1205     }
1206
1207     if ( iface->i_flags & IFACE_PHASE1 ) {
1208         setaddr( iface, IFACE_PHASE1, 0,
1209                 iface->i_caddr.sat_addr.s_node, 0, 0 );
1210
1211         if ( iface->i_flags & IFACE_LOOPBACK ) {
1212             iface->i_flags |= IFACE_CONFIG | IFACE_ADDR;
1213             if ( ciface == iface ) {
1214                 ciface = ciface->i_next;
1215                 bootaddr( ciface );
1216             }
1217
1218         } else if (rtmp_request( iface ) < 0) {
1219           syslog(LOG_ERR, "bootaddr (rtmp_request): %m");
1220           atalkd_exit(1);
1221         }
1222
1223     } else {
1224         setaddr( iface, IFACE_PHASE2, iface->i_caddr.sat_addr.s_net,
1225                 iface->i_caddr.sat_addr.s_node,
1226                 iface->i_rt->rt_firstnet, iface->i_rt->rt_lastnet );
1227
1228         if ( iface->i_flags & IFACE_LOOPBACK ) {
1229             iface->i_flags |= IFACE_CONFIG | IFACE_ADDR;
1230             if ( ciface == iface ) {
1231                 ciface = ciface->i_next;
1232                 bootaddr( ciface );
1233             }
1234             
1235         } else if (zip_getnetinfo( iface ) < 0) {
1236           syslog(LOG_ERR, "bootaddr (zip_getnetinfo): %m");
1237           atalkd_exit(1);
1238         }
1239     }
1240     ++iface->i_time;
1241     iface->i_flags |= IFACE_ADDR;
1242     stabletimer = UNSTABLE;
1243 }
1244
1245
1246 /*
1247  * Change setaddr()
1248  * to manage the i_ports field and the fds for select().
1249  */
1250 void setaddr( iface, phase, net, node, first, last )
1251     struct interface    *iface;
1252     u_int8_t            phase;
1253     u_int16_t           net;
1254     u_int8_t            node;
1255     u_int16_t           first, last;
1256 {
1257     int                 i;
1258     struct atserv       *as;
1259     struct atport       *ap;
1260     struct servent      *se;
1261     struct sockaddr_at  sat;
1262     struct netrange     nr;
1263
1264     if ( iface->i_ports == NULL ) {     /* allocate port structures */
1265         for ( i = 0, as = atserv; i < atservNATSERV; i++, as++ ) {
1266             if (( se = getservbyname( as->as_name, "ddp" )) == NULL ) {
1267                 syslog( LOG_INFO, "%s: service unknown", as->as_name );
1268             } else {
1269                 as->as_port = ntohs( se->s_port );
1270             }
1271             if (( ap = (struct atport *)malloc( sizeof( struct atport ))) ==
1272                     NULL ) {
1273                 syslog( LOG_ERR, "malloc: %m" );
1274                 atalkd_exit( 1 );
1275             }
1276             ap->ap_fd = 0;
1277             ap->ap_next = iface->i_ports;
1278             ap->ap_iface = iface;
1279             ap->ap_port = as->as_port;
1280             ap->ap_packet = as->as_packet;
1281
1282             iface->i_ports = ap;
1283         }
1284     } else {                            /* close ports */
1285         for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1286             (void)close( ap->ap_fd );
1287         }
1288     }
1289
1290 #ifdef BSD4_4
1291     iface->i_addr.sat_len = sizeof( struct sockaddr_at );
1292 #endif BSD4_4
1293     iface->i_addr.sat_family = AF_APPLETALK;
1294     iface->i_addr.sat_addr.s_net = net;
1295     iface->i_addr.sat_addr.s_node = node;
1296
1297     nr.nr_phase = phase;
1298     nr.nr_firstnet = first;
1299     nr.nr_lastnet = last;
1300     memcpy( iface->i_addr.sat_zero, &nr, sizeof( struct netrange ));
1301
1302     if ( ifconfig( iface->i_name, SIOCSIFADDR, &iface->i_addr )) {
1303       syslog( LOG_ERR, "setifaddr: %s (%u-%u): %m. try specifying a \
1304 smaller net range.", iface->i_name, ntohs(first), ntohs(last));
1305         atalkd_exit( 1 );
1306     }
1307     if ( ifconfig( iface->i_name, SIOCGIFADDR, &iface->i_addr )) {
1308         syslog( LOG_ERR, "getifaddr: %s: %m", iface->i_name );
1309         atalkd_exit( 1 );
1310     }
1311
1312     /* open ports */
1313     i = 1; /* enable broadcasts */
1314 #if defined(__svr4__) 
1315     syslog(LOG_INFO, "setsockopt incompatible w/ Solaris STREAMS module.");
1316 #endif
1317     for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1318         if (( ap->ap_fd = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1319             syslog( LOG_ERR, "socket: %m" );
1320             atalkd_exit( 1 );
1321         }
1322 #if !defined(__svr4__)
1323         setsockopt(ap->ap_fd, SOL_SOCKET, SO_BROADCAST, &i, sizeof(i));
1324 #endif
1325
1326         memset( &sat, 0, sizeof( struct sockaddr_at ));
1327 #ifdef BSD4_4
1328         sat.sat_len = sizeof( struct sockaddr_at );
1329 #endif BSD4_4
1330         sat.sat_family = AF_APPLETALK;
1331         sat.sat_addr.s_net = iface->i_addr.sat_addr.s_net;
1332         sat.sat_addr.s_node = iface->i_addr.sat_addr.s_node;
1333         sat.sat_port = ap->ap_port;
1334
1335         if ( bind( ap->ap_fd, (struct sockaddr *)&sat,
1336                 sizeof( struct sockaddr_at )) < 0 ) {
1337             syslog( LOG_ERR, "bind %u.%u:%u: %m",
1338                     ntohs( sat.sat_addr.s_net ),
1339                     sat.sat_addr.s_node, sat.sat_port );
1340 #ifdef SIOCDIFADDR
1341             /* remove all interfaces if we have a problem with bind */
1342             for (iface = interfaces; iface; iface = iface->i_next) {
1343               if (ifconfig( iface->i_name, SIOCDIFADDR, &iface->i_addr )) {
1344 #ifdef SIOCATALKDIFADDR
1345 #if (SIOCDIFADDR != SIOCATALKDIFADDR)
1346                 ifconfig( iface->i_name, SIOCATALKDIFADDR, &iface->i_addr );
1347 #endif          
1348 #endif
1349               }
1350             }
1351 #endif 
1352             atalkd_exit( 1 );
1353         }
1354     }
1355
1356     /* recalculate nfds and fds */
1357     FD_ZERO( &fds );
1358     for ( nfds = 0, iface = interfaces; iface; iface = iface->i_next ) {
1359         for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
1360             FD_SET( ap->ap_fd, &fds );
1361             if ( ap->ap_fd > nfds ) {
1362                 nfds = ap->ap_fd;
1363             }
1364         }
1365     }
1366     nfds++;
1367 }
1368
1369 int ifconfig( iname, cmd, sa )
1370     const char          *iname;
1371     unsigned long       cmd;
1372     struct sockaddr_at  *sa;
1373 {
1374     struct ifreq        ifr;
1375     int                 s;
1376
1377     memset(&ifr, 0, sizeof(ifr));
1378     strcpy( ifr.ifr_name, iname );
1379     ifr.ifr_addr = *(struct sockaddr *)sa;
1380
1381     if (( s = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
1382         return( 1 );
1383     }
1384     if ( ioctl( s, cmd, &ifr ) < 0 ) {
1385         close(s);
1386         return( 1 );
1387     }
1388     close( s );
1389     if ( cmd == SIOCGIFADDR ) {
1390         *(struct sockaddr *)sa = ifr.ifr_addr;
1391     }
1392     return( 0 );
1393 }
1394
1395 void dumpconfig( iface )
1396     struct interface    *iface;
1397 {
1398     struct list         *l;
1399
1400     printf( "%s", iface->i_name );
1401     if ( iface->i_flags & IFACE_RSEED ) {
1402         printf( " -router" );
1403     } else if ( iface->i_flags & IFACE_SEED ) {
1404         printf( " -seed" );
1405     }
1406
1407     if ( iface->i_flags & IFACE_DONTROUTE) 
1408         printf( " -dontroute");
1409
1410     printf( " -phase" );
1411     if ( iface->i_flags & IFACE_PHASE1 ) {
1412         printf( " 1" );
1413     } else {
1414         printf( " 2" );
1415     }
1416     printf( " -net %d", ntohs( iface->i_rt->rt_firstnet ));
1417     if ( iface->i_rt->rt_lastnet != iface->i_rt->rt_firstnet ) {
1418         printf( "-%d", ntohs( iface->i_rt->rt_lastnet ));
1419     }
1420     printf( " -addr %u.%u", ntohs( iface->i_addr.sat_addr.s_net ),
1421             iface->i_addr.sat_addr.s_node );
1422     printf( " -caddr %u.%u", ntohs( iface->i_caddr.sat_addr.s_net ),
1423             iface->i_caddr.sat_addr.s_node );
1424     for ( l = iface->i_rt->rt_zt; l; l = l->l_next ) {
1425         printf( " -zone %.*s", ((struct ziptab *)l->l_data)->zt_len,
1426                 ((struct ziptab *)l->l_data)->zt_name );
1427     }
1428     printf( "\n" );
1429 }
1430
1431 #ifdef DEBUG
1432 void dumproutes()
1433 {
1434     struct interface    *iface;
1435     struct rtmptab      *rtmp;
1436     struct list         *l;
1437     struct ziptab       *zt;
1438
1439     for ( iface = interfaces; iface; iface = iface->i_next ) {
1440         for ( rtmp = iface->i_rt; rtmp; rtmp = rtmp->rt_inext ) {
1441             if ( rtmp->rt_gate == 0 ) {
1442                 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
1443                     printf( "%u-%u", ntohs( rtmp->rt_firstnet ),
1444                             ntohs( rtmp->rt_lastnet ));
1445                 } else {
1446                     printf( "%u", ntohs( rtmp->rt_firstnet ));
1447                 }
1448             } else {
1449                 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
1450                     printf( "%u.%u for %u-%u",
1451                             ntohs( rtmp->rt_gate->g_sat.sat_addr.s_net ),
1452                             rtmp->rt_gate->g_sat.sat_addr.s_node,
1453                             ntohs( rtmp->rt_firstnet ),
1454                             ntohs( rtmp->rt_lastnet ));
1455                 } else {
1456                     printf( "%u.%u for %u",
1457                             ntohs( rtmp->rt_gate->g_sat.sat_addr.s_net ),
1458                             rtmp->rt_gate->g_sat.sat_addr.s_node,
1459                             ntohs( rtmp->rt_firstnet ));
1460                 }
1461             }
1462
1463             if ( rtmp->rt_iprev == 0 && rtmp != iface->i_rt ) {
1464                 printf( " *" );
1465             }
1466
1467             for ( l = rtmp->rt_zt; l; l = l->l_next ) {
1468                 zt = (struct ziptab *)l->l_data;
1469                 printf( " %.*s", zt->zt_len, zt->zt_name );
1470             }
1471
1472             printf( "\n" );
1473         }
1474     }
1475
1476     printf( "\n" );
1477     fflush( stdout );
1478 }
1479
1480 void dumpzones()
1481 {
1482     struct interface    *iface;
1483     struct rtmptab      *rtmp;
1484     struct list         *l;
1485     struct ziptab       *zt;
1486
1487     for ( zt = ziptab; zt; zt = zt->zt_next ) {
1488         printf( "%.*s", zt->zt_len, zt->zt_name );
1489         for ( l = zt->zt_rt; l; l = l->l_next ) {
1490             rtmp = (struct rtmptab *)l->l_data;
1491             if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
1492                 printf( " %u-%u", ntohs( rtmp->rt_firstnet ),
1493                         ntohs( rtmp->rt_lastnet ));
1494             } else {
1495                 printf( " %u", ntohs( rtmp->rt_firstnet ));
1496             }
1497             if ( rtmp->rt_iprev == 0 && rtmp->rt_gate != 0 ) {
1498                 printf( "*" );
1499             }
1500         }
1501         printf( "\n" );
1502     }
1503
1504     printf( "\n" );
1505     fflush( stdout );
1506 }
1507 #endif DEBUG