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