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