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