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