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