]> arthur.barton.de Git - netatalk.git/blobdiff - etc/atalkd/main.c
atalkd don't spam syslog if an interface is down, XXX atalkd still advertise routes...
[netatalk.git] / etc / atalkd / main.c
index 34d6f9d1ef84a2632a4b101be661d13221c483e8..469678d3db9ec13273511e7a2157a426e7624a25 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: main.c,v 1.16 2002-09-29 23:24:47 sibaz Exp $
+ * $Id: main.c,v 1.25 2009-12-13 02:21:47 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved. See COPYRIGHT.
 
 #include <sys/param.h>
 #include <sys/socket.h>
-#if defined( sun ) && defined( __svr4__ )
-#include </usr/ucbinclude/sys/file.h>
-#else /* sun __svr4__ */
 #include <sys/file.h>
-#endif /* sun __svr4__ */
 #include <sys/time.h>
 #include <sys/resource.h>
 #include <sys/ioctl.h>
@@ -31,6 +27,9 @@
 #ifndef WIFEXITED
 #define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
 #endif /* ! WIFEXITED */
+#ifndef WIFSTOPPED
+#define WIFSTOPPED(status) (((status) & 0xff) == 0x7f)
+#endif
 
 #include <errno.h>
 #ifdef TRU64
@@ -56,6 +55,7 @@
 #include <atalk/compat.h>
 #include <atalk/zip.h>
 #include <atalk/rtmp.h>
+#include <atalk/nbp.h>
 #include <atalk/ddp.h>
 #include <atalk/atp.h>
 #include <atalk/paths.h>
@@ -71,6 +71,7 @@
 #include "list.h"
 #include "rtmp.h"
 #include "zip.h"
+#include "nbp.h"
 #include "atserv.h"
 #include "main.h"
 
@@ -98,34 +99,33 @@ int ifconfig(const char *iname, unsigned long cmd, struct sockaddr_at *sa);
 
 #define PKTSZ  1024
 
-extern int     rtmp_packet();
-extern int     nbp_packet();
-extern int     aep_packet();
-extern int     zip_packet();
+extern int aep_packet(struct atport *ap, struct sockaddr_at *from, char *data, int len);
 
 int            rtfd;
+int            transition = 0;
+int            stabletimer, newrtmpdata = 0;
 
-struct atserv  atserv[] = {
+static struct atserv   atserv[] = {
     { "rtmp",          1,      rtmp_packet },          /* 0 */
     { "nbp",           2,      nbp_packet },           /* 1 */
     { "echo",          4,      aep_packet },           /* 2 */
     { "zip",           6,      zip_packet },           /* 3 */
 };
-int            atservNATSERV = elements( atserv );
+static int             atservNATSERV = elements( atserv );
 
 struct interface       *interfaces = NULL, *ciface = NULL;
 
-int            debug = 0, quiet = 0, chatty = 0;
-char           *configfile = NULL;
-int            ziptimeout = 0, transition = 0;
-int            stabletimer, stable = 0, newrtmpdata = 0, noparent = 0;
-static int     ninterfaces;
-int            defphase = IFACE_PHASE2;
-int            nfds = 0;
-fd_set         fds;
-char           Packet[ PKTSZ ];
-char           *version = VERSION;
-static char     *pidfile = _PATH_ATALKDLOCK;
+static int             debug = 0, quiet = 0, chatty = 0;
+static char            *configfile = NULL;
+static int             ziptimeout = 0;
+static int             stable = 0, noparent = 0;
+static int             ninterfaces;
+static int             defphase = IFACE_PHASE2;
+static int             nfds = 0;
+static fd_set          fds;
+static char            Packet[ PKTSZ ];
+static char            *version = VERSION;
+static char            *pidfile = _PATH_ATALKDLOCK;
 
 
 /* from config.c */
@@ -153,6 +153,10 @@ static void atalkd_exit(const int i)
              ntohs(iface->i_addr.sat_addr.s_net), 
              iface->i_addr.sat_addr.s_node, strerror(errno));
     }
+#ifdef linux
+    if (!(iface->i_flags & IFACE_WASALLMULTI) && (iface->i_flags & IFACE_ALLMULTI))
+        ifsetallmulti(iface->i_name, 0);
+#endif /* linux */
   }
 #endif /* SOPCDOFADDR */
 
@@ -160,8 +164,32 @@ static void atalkd_exit(const int i)
   exit(i);
 }
 
+/* XXX need better error handling for gone interfaces, delete routes and so on 
+ * moreover there's no way to put an interface back short of restarting atalkd
+ * thus after the first time, silently fail
+*/
+static ssize_t sendto_iface(struct interface *iface, int sockfd, const void *buf, size_t len, 
+                       const struct sockaddr_at         *dest_addr)
+{
+    ssize_t ret = sendto( sockfd, buf, len, 0, (struct sockaddr *)dest_addr, sizeof( struct sockaddr_at ));
+
+    if (ret < 0 ) {
+        if (!(iface->i_flags & IFACE_ERROR)) {
+            LOG(log_error, logtype_atalkd, "as_timer sendto %u.%u (%u): %s",
+                                   ntohs( dest_addr->sat_addr.s_net ),
+                                   dest_addr->sat_addr.s_node,
+                                   ntohs( iface->i_rt->rt_firstnet ),
+                                   strerror(errno) );
+        }
+        iface->i_flags |= IFACE_ERROR;
+    }
+    else {
+        iface->i_flags &= ~IFACE_ERROR;
+    }
+    return ret;
+}
 
-static void as_timer(int sig)
+static void as_timer(int sig _U_)
 {
     struct sockaddr_at sat;
     struct ziphdr      zh;
@@ -176,7 +204,10 @@ static void as_timer(int sig)
     int                        sentzipq = 0;
     int                        n, cc;
 
+    ap=zap=rap=NULL;
+
     memset(&sat, 0, sizeof( struct sockaddr_at ));
+
     for ( iface = interfaces; iface; iface = iface->i_next ) {
        if ( iface->i_flags & IFACE_LOOPBACK ) {
            continue;
@@ -190,8 +221,7 @@ static void as_timer(int sig)
            }
        }
 
-       if (( iface->i_flags & ( IFACE_ADDR|IFACE_CONFIG|IFACE_NOROUTER )) ==
-               IFACE_ADDR ) {
+       if (( iface->i_flags & ( IFACE_ADDR|IFACE_CONFIG|IFACE_NOROUTER )) == IFACE_ADDR ) {
            if ( iface->i_time < 3 ) {
                if ( iface->i_flags & IFACE_PHASE1 ) {
                  if (rtmp_request( iface ) < 0) {
@@ -215,10 +245,8 @@ static void as_timer(int sig)
                         * No seed info, and we've got multiple interfaces.
                         * Wait forever.
                         */
-                       LOG(log_info, logtype_atalkd,
-                               "as_timer multiple interfaces, no seed" );
-                       LOG(log_info, logtype_atalkd, "as_timer can't configure %s",
-                               iface->i_name );
+                       LOG(log_info, logtype_atalkd, "as_timer multiple interfaces, no seed" );
+                       LOG(log_info, logtype_atalkd, "as_timer can't configure %s", iface->i_name );
                        LOG(log_info, logtype_atalkd, "as_timer waiting for router" );
                        iface->i_time = 0;
                        continue;
@@ -229,8 +257,7 @@ static void as_timer(int sig)
                         */
                        iface->i_flags |= IFACE_CONFIG;
                        for ( zt = iface->i_czt; zt; zt = zt->zt_next ) {
-                           if (addzone( iface->i_rt, zt->zt_len, 
-                                        zt->zt_name) < 0) {
+                           if (addzone( iface->i_rt, zt->zt_len, zt->zt_name) < 0) {
                              LOG(log_error, logtype_atalkd, "addzone: %s", strerror(errno));
                              atalkd_exit(1);
                            }
@@ -240,26 +267,20 @@ static void as_timer(int sig)
                            iface->i_rt->rt_flags |= RTMPTAB_HASZONES;
                        }
                        if ( iface->i_flags & IFACE_PHASE1 ) {
-                           LOG(log_info, logtype_atalkd,
-                                   "as_timer configured %s phase 1 from seed",
-                                   iface->i_name );
+                           LOG(log_info, logtype_atalkd, "as_timer configured %s phase 1 from seed", iface->i_name );
                            setaddr( iface, IFACE_PHASE1,
                                    iface->i_caddr.sat_addr.s_net,
                                    iface->i_addr.sat_addr.s_node,
                                    iface->i_caddr.sat_addr.s_net,
                                    iface->i_caddr.sat_addr.s_net );
                        } else {
-                           LOG(log_info, logtype_atalkd,
-                                   "as_timer configured %s phase 2 from seed",
-                                   iface->i_name );
+                           LOG(log_info, logtype_atalkd, "as_timer configured %s phase 2 from seed", iface->i_name );
                        }
 
                        if ( looproute( iface, RTMP_ADD )) { /* -1 or 1 */
-                           LOG(log_error, logtype_atalkd,
-                                   "as_timer: can't route %u.%u to loop: %s",
-                                   ntohs( iface->i_addr.sat_addr.s_net ),
-                                   iface->i_addr.sat_addr.s_node,
-                                   strerror(errno) );
+                           LOG(log_error, logtype_atalkd, "as_timer: can't route %u.%u to loop: %s", 
+                                   ntohs( iface->i_addr.sat_addr.s_net ),
+                                   iface->i_addr.sat_addr.s_node, strerror(errno) );
                            atalkd_exit( 1 );
                        }
                        if ( iface == ciface ) {
@@ -277,16 +298,12 @@ static void as_timer(int sig)
                    if ( iface->i_flags & IFACE_PHASE2 ) {
                        iface->i_rt->rt_firstnet = 0;
                        iface->i_rt->rt_lastnet = htons( STARTUP_LASTNET );
-                       setaddr( iface, IFACE_PHASE2,
-                               iface->i_addr.sat_addr.s_net,
-                               iface->i_addr.sat_addr.s_node,
+                       setaddr( iface, IFACE_PHASE2, iface->i_addr.sat_addr.s_net, iface->i_addr.sat_addr.s_node,
                                0, htons( STARTUP_LASTNET ));
                    }
                    if ( looproute( iface, RTMP_ADD ) ) { /* -1 or 1 */
-                       LOG(log_error, logtype_atalkd,
-                               "as_timer: can't route %u.%u to loopback: %s",
-                               ntohs( iface->i_addr.sat_addr.s_net ),
-                               iface->i_addr.sat_addr.s_node,
+                       LOG(log_error, logtype_atalkd, "as_timer: can't route %u.%u to loopback: %s",
+                               ntohs( iface->i_addr.sat_addr.s_net ), iface->i_addr.sat_addr.s_node,
                                strerror(errno) );
                        atalkd_exit( 1 );
                    }
@@ -318,14 +335,12 @@ static void as_timer(int sig)
             * our zone has gone away.
             */
            if ( ++gate->g_state >= RTMPTAB_BAD ) {
-               LOG(log_info, logtype_atalkd, "as_timer gateway %u.%u down",
-                       ntohs( gate->g_sat.sat_addr.s_net ),
+               LOG(log_info, logtype_atalkd, "as_timer gateway %u.%u down", ntohs( gate->g_sat.sat_addr.s_net ),
                        gate->g_sat.sat_addr.s_node );
                rtmp = gate->g_rt;
                while ( rtmp ) {
                    frtmp = rtmp->rt_next;
-                   if ( rtmp->rt_hops == RTMPHOPS_POISON ||
-                           rtmp->rt_iprev == 0 ) {
+                   if ( rtmp->rt_hops == RTMPHOPS_POISON || rtmp->rt_iprev == NULL ) {
                        rtmp_free( rtmp );
                    } else {
                        rtmp->rt_hops = RTMPHOPS_POISON;
@@ -339,13 +354,13 @@ static void as_timer(int sig)
                    }
                    rtmp = frtmp;
                }
-               if ( gate->g_rt == 0 ) {
-                   if ( gate->g_prev == 0 ) {
+               if ( gate->g_rt == NULL ) {
+                   if ( gate->g_prev == NULL ) {
                        gate->g_iface->i_gate = gate->g_next;
                    } else {
                        gate->g_prev->g_next = gate->g_next;
                    }
-                   if ( gate->g_next != 0 ) {
+                   if ( gate->g_next != NULL ) {
                        gate->g_next->g_prev = gate->g_prev;
                    }
                    fgate = gate;       /* can't free here, just mark it */
@@ -360,8 +375,7 @@ static void as_timer(int sig)
                 * if we're not a seed router.
                 */
 
-               if ( gate->g_iface->i_gate == 0 && 
-                    ((iface->i_flags & IFACE_SEED) == 0)) {
+               if ( gate->g_iface->i_gate == NULL && ((iface->i_flags & IFACE_SEED) == 0)) {
                    gate->g_iface->i_flags |= IFACE_NOROUTER;
                    gate->g_iface->i_flags &= ~IFACE_CONFIG;
 
@@ -418,7 +432,7 @@ static void as_timer(int sig)
                 */
                if ( rtmp->rt_state >= RTMPTAB_BAD ) {
                    frtmp = rtmp->rt_next;
-                   if ( rtmp->rt_iprev == 0 ) {        /* not in use */
+                   if ( rtmp->rt_iprev == NULL ) {     /* not in use */
                        rtmp_free( rtmp );
                    } else {                            /* in use */
                        if ( rtmp->rt_hops == RTMPHOPS_POISON ) {
@@ -440,8 +454,7 @@ static void as_timer(int sig)
                /*
                 * Do ZIP lookups.
                 */
-               if ( rtmp->rt_iprev &&
-                       ( rtmp->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
+               if ( rtmp->rt_iprev && ( rtmp->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
                    if ( data + sizeof( u_short ) > end || n == 255 ) {
                        /* send what we've got */
                        zh.zh_op = ZIPOP_QUERY;
@@ -451,11 +464,7 @@ static void as_timer(int sig)
                        *data++ = DDPTYPE_ZIP;
                        memcpy( data, &zh, sizeof( struct ziphdr ));
 
-                       if ( sendto( zap->ap_fd, packet, cc, 0,
-                               (struct sockaddr *)&sat,
-                               sizeof( struct sockaddr_at )) < 0 ) {
-                           LOG(log_error, logtype_atalkd, "as_timer sendto: %s", strerror(errno) );
-                       }
+                       sendto_iface(iface,  zap->ap_fd, packet, cc, &sat);
                        sentzipq = 1;
 
                        n = 0;
@@ -473,8 +482,7 @@ static void as_timer(int sig)
                     * ask about, and warn that we can't get it's zone.
                     */
                    if ( rtmp->rt_nzq++ == 3 ) {
-                       LOG(log_info, logtype_atalkd, "as_timer can't get zone for %u",
-                               ntohs( rtmp->rt_firstnet ));
+                       LOG(log_info, logtype_atalkd, "as_timer can't get zone for %u", ntohs( rtmp->rt_firstnet ));
                    }
                    if ( rtmp->rt_nzq > 3 ) {
                        if ( ziptimeout ) {
@@ -501,10 +509,7 @@ static void as_timer(int sig)
                *data++ = DDPTYPE_ZIP;
                memcpy( data, &zh, sizeof( struct ziphdr ));
 
-               if ( sendto( zap->ap_fd, packet, cc, 0, (struct sockaddr *)&sat,
-                       sizeof( struct sockaddr_at )) < 0 ) {
-                   LOG(log_error, logtype_atalkd, "as_timer sendto: %s", strerror(errno) );
-               }
+               sendto_iface( iface, zap->ap_fd, packet, cc, &sat);
            }
        }
        if ( fgate ) {
@@ -570,31 +575,27 @@ static void as_timer(int sig)
                 */
                for ( rtmp = iface2->i_rt; rtmp; rtmp = rtmp->rt_inext ) {
                    /* don't broadcast routes we have no zone for */
-                   if ( rtmp->rt_zt == 0 ||
+                   if ( rtmp->rt_zt == NULL ||
                            ( rtmp->rt_flags & RTMPTAB_ZIPQUERY ) ||
                            ( rtmp->rt_flags & RTMPTAB_HASZONES ) == 0 ) {
                        continue;
                    }
 
+                   /* split horizon */
+                   if (rtmp->rt_iface == iface) {
+                       continue;
+                   }
+
                    if ((( rtmp->rt_flags & RTMPTAB_EXTENDED ) &&
                            data + 2 * SZ_RTMPTUPLE > end ) ||
                            data + SZ_RTMPTUPLE > end ) {
-                       if ( sendto( rap->ap_fd, packet, data - packet, 0,
-                               (struct sockaddr *)&sat,
-                               sizeof( struct sockaddr_at )) < 0 ) {
-                           LOG(log_error, logtype_atalkd, "as_timer sendto %u.%u (%u): %s",
-                                   ntohs( sat.sat_addr.s_net ),
-                                   sat.sat_addr.s_node,
-                                   ntohs( iface->i_rt->rt_firstnet ),
-                                   strerror(errno) );
-                       }
+
+                       sendto_iface(iface,rap->ap_fd, packet, data - packet, &sat);
 
                        if ( iface->i_flags & IFACE_PHASE2 ) {
-                           data = packet + 1 + sizeof( struct rtmp_head ) +
-                                   2 * SZ_RTMPTUPLE;
+                           data = packet + 1 + sizeof( struct rtmp_head ) + 2 * SZ_RTMPTUPLE;
                        } else {
-                           data = packet + 1 + sizeof( struct rtmp_head ) +
-                                   SZ_RTMPTUPLE;
+                           data = packet + 1 + sizeof( struct rtmp_head ) + SZ_RTMPTUPLE;
                        }
                        n = 0;
                    }
@@ -619,15 +620,7 @@ static void as_timer(int sig)
 
            /* send rest */
            if ( n ) {
-               if ( sendto( rap->ap_fd, packet, data - packet, 0,
-                       (struct sockaddr *)&sat,
-                       sizeof( struct sockaddr_at )) < 0 ) {
-                   LOG(log_error, logtype_atalkd, "as_timer sendto %u.%u (%u): %s",
-                           ntohs( sat.sat_addr.s_net ),
-                           sat.sat_addr.s_node,
-                           ntohs( iface->i_rt->rt_firstnet ),
-                           strerror(errno) );
-               }
+               sendto_iface(iface, rap->ap_fd, packet, data - packet, &sat);
            }
        }
     }
@@ -686,7 +679,7 @@ consistency()
        for ( lr = zt->zt_rt; lr; lr = lr->l_next ) {
            rtmp = (struct rtmptab *)lr->l_data;
            if ( rtmp->rt_iprev == 0 && rtmp->rt_gate != 0 ) {
-               LOG(log_error, logtype_atalkd, "%.*s has %u-%u (unused)\n",
+               LOG(log_error, logtype_atalkd, "%.*s has %u-%u (unused)",
                        zt->zt_len, zt->zt_name, ntohs( rtmp->rt_firstnet ),
                        ntohs( rtmp->rt_lastnet ));
                atalkd_exit(1);
@@ -697,7 +690,7 @@ consistency()
                }
            }
            if ( lz == 0 ) {
-               LOG(log_error, logtype_atalkd, "no map from %u-%u to %.*s\n", 
+               LOG(log_error, logtype_atalkd, "no map from %u-%u to %.*s", 
                        ntohs( rtmp->rt_firstnet ),
                        ntohs( rtmp->rt_lastnet ),
                        zt->zt_len, zt->zt_name );
@@ -708,10 +701,8 @@ consistency()
 }
 #endif /* DEBUG */
 
-#if !defined( ibm032 ) && !defined( _IBMR2 )
-    void
-#endif /* ! ibm032 && ! _IBMR2 */
-as_debug()
+static void
+as_debug(int sig _U_)
 {
     struct interface   *iface;
     struct list                *l;
@@ -812,10 +803,8 @@ as_debug()
 /*
  * Called when SIGTERM is recieved.  Remove all routes and then exit.
  */
-#if !defined( ibm032 ) && !defined( _IBMR2 )
-    void
-#endif /* ! ibm032 && ! _IBMR2 */
-as_down()
+static void
+as_down(int sig _U_)
 {
     struct interface   *iface;
     struct gate                *gate;
@@ -848,9 +837,7 @@ as_down()
     atalkd_exit( 0 );
 }
 
-int main( ac, av )
-    int                ac;
-    char       **av;
+int main( int ac, char **av)
 {
     extern char         *optarg;
     extern int          optind;
@@ -858,14 +845,15 @@ int main( ac, av )
     struct sockaddr_at sat;
     struct sigaction   sv;
     struct itimerval   it;
+    sigset_t            signal_set, old_set;
+    
     struct interface   *iface;
     int                        status;
     struct atport      *ap;
     fd_set             readfds;
-    int                        i, mask, c;
+    int                        i, c;
     SOCKLEN_T          fromlen;
     char               *prog;
-;
 
     while (( c = getopt( ac, av, "12qsdtf:P:v" )) != EOF ) {
        switch ( c ) {
@@ -1020,6 +1008,12 @@ int main( ac, av )
        exit( 1 );
     }
 
+    /*
+     * Set process name for logging
+     */
+
+    set_processname("atalkd");
+
     /* do this here so that we can use ifconfig */
 #ifdef __svr4__
     if ( plumb() < 0 ) {
@@ -1106,6 +1100,9 @@ int main( ac, av )
     }
 #endif /* BSD4_4 */
 
+    ciface = interfaces;
+    bootaddr( ciface );
+
     memset(&sv, 0, sizeof(sv));
     sv.sa_handler = as_down;
     sigemptyset( &sv.sa_mask );
@@ -1149,8 +1146,14 @@ int main( ac, av )
        atalkd_exit( 1 );
     }
 
-    ciface = interfaces;
-    bootaddr( ciface );
+    sigemptyset( &signal_set );
+    sigaddset(&signal_set, SIGALRM);
+#if 0
+    /* don't block SIGTERM */
+    sigaddset(&signal_set, SIGTERM);
+#endif
+    sigaddset(&signal_set, SIGUSR1);
+
     for (;;) {
        readfds = fds;
        if ( select( nfds, &readfds, NULL, NULL, NULL) < 0 ) {
@@ -1173,7 +1176,7 @@ int main( ac, av )
                            LOG(log_error, logtype_atalkd, "recvfrom: %s", strerror(errno) );
                            continue;
                        }
-#ifdef DEBUG
+#ifdef DEBUG1
                        if ( debug ) {
                            printf( "packet from %u.%u on %s (%x) %d (%d)\n",
                                    ntohs( sat.sat_addr.s_net ),
@@ -1181,16 +1184,12 @@ int main( ac, av )
                                    iface->i_flags, ap->ap_port, ap->ap_fd );
                            bprint( Packet, c );
                        }
-#endif /* DEBUG */
-#ifdef __svr4__
-                       if ( sighold( SIGALRM ) || sighold( SIGUSR1 )) {
-                           LOG(log_error, logtype_atalkd, "sighold: %s", strerror(errno) );
+#endif 
+                       if (sigprocmask(SIG_BLOCK, &signal_set, &old_set) < 0) {
+                           LOG(log_error, logtype_atalkd, "sigprocmask: %s", strerror(errno) );
                            atalkd_exit( 1 );
                        }
-#else /* __svr4__ */
-                       mask = sigsetmask( sigmask( SIGALRM ) |
-                               sigmask( SIGUSR1 ));
-#endif /* __svr4__ */
+
                        if (( *ap->ap_packet )( ap, &sat, Packet, c ) < 0) {
                          LOG(log_error, logtype_atalkd, "ap->ap_packet: %s", strerror(errno));
                          atalkd_exit(1);
@@ -1198,15 +1197,12 @@ int main( ac, av )
 
 #ifdef DEBUG
                        consistency();
-#endif /* DEBUG */
-#ifdef __svr4__
-                       if ( sigrelse( SIGUSR1 ) || sigrelse( SIGALRM )) {
-                           LOG(log_error, logtype_atalkd, "sigrelse: %s", strerror(errno) );
+#endif 
+                       if (sigprocmask(SIG_SETMASK, &old_set, NULL) < 0) {
+                           LOG(log_error, logtype_atalkd, "sigprocmask old set: %s", strerror(errno) );
                            atalkd_exit( 1 );
                        }
-#else /* __svr4__ */
-                       sigsetmask( mask );
-#endif /* __svr4__ */
+
                    }
                }
            }
@@ -1219,10 +1215,9 @@ int main( ac, av )
  * and rtmp_packet()) to set the initial "bootstrapping" address
  * on an interface.
  */
-void bootaddr( iface )
-    struct interface   *iface;
+void bootaddr(struct interface *iface)
 {
-    if ( iface == 0 ) {
+    if ( iface == NULL ) {
        return;
     }
 
@@ -1336,7 +1331,8 @@ smaller net range.", iface->i_name, ntohs(first), ntohs(last), strerror(errno));
 
     /* open ports */
     i = 1; /* enable broadcasts */
-#ifdef __svr4__ 
+#if 0
+    /* useless message, no? */
     LOG(log_info, logtype_atalkd, "setsockopt incompatible w/ Solaris STREAMS module.");
 #endif /* __svr4__ */
     for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
@@ -1391,10 +1387,42 @@ smaller net range.", iface->i_name, ntohs(first), ntohs(last), strerror(errno));
     nfds++;
 }
 
-int ifconfig( iname, cmd, sa )
-    const char         *iname;
-    unsigned long      cmd;
-    struct sockaddr_at *sa;
+int ifsetallmulti (const char *iname, int set)
+{
+    int sock;
+    struct ifreq ifr;
+
+    memset(&ifr, 0, sizeof(ifr));
+
+    if (( sock = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) {
+        return( -1 );
+    }
+
+    /* get interface config */
+    strlcpy(ifr.ifr_name, iname, sizeof(ifr.ifr_name));
+    if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
+        close(sock);
+        return (-1);
+    }
+
+    /* should we set or unset IFF_ALLMULTI */
+    if (set)
+           ifr.ifr_flags |= IFF_ALLMULTI;
+    else
+           ifr.ifr_flags &= ~IFF_ALLMULTI;
+
+    /* set interface config */
+    strlcpy(ifr.ifr_name, iname, sizeof(ifr.ifr_name));
+    if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) {
+        close(sock);   
+        return -1;
+    }
+
+    close(sock);
+    return (0);
+}
+
+int ifconfig( const char *iname, unsigned long cmd, struct sockaddr_at *sa)
 {
     struct ifreq       ifr;
     int                        s;
@@ -1417,8 +1445,7 @@ int ifconfig( iname, cmd, sa )
     return( 0 );
 }
 
-void dumpconfig( iface )
-    struct interface   *iface;
+void dumpconfig( struct interface *iface)
 {
     struct list                *l;
 
@@ -1454,7 +1481,7 @@ void dumpconfig( iface )
 }
 
 #ifdef DEBUG
-void dumproutes()
+void dumproutes(void)
 {
     struct interface   *iface;
     struct rtmptab     *rtmp;
@@ -1502,7 +1529,7 @@ void dumproutes()
     fflush( stdout );
 }
 
-void dumpzones()
+void dumpzones(void)
 {
     struct interface   *iface;
     struct rtmptab     *rtmp;