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