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