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