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