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