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