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