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