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