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