/*
- * $Id: config.c,v 1.13 2003-03-18 23:32:17 srittau Exp $
+ * $Id: config.c,v 1.20 2009-10-29 11:35:58 didg Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#include <sys/stropts.h>
#endif /* __svr4__ */
+#include <atalk/unicode.h>
#include "interface.h"
#include "multicast.h"
#include "rtmp.h"
#include "zip.h"
#include "list.h"
+#include "main.h"
#ifndef IFF_SLAVE /* a little backward compatibility */
#define IFF_SLAVE 0
#endif /* IFF_SLAVE */
-int router(), dontroute(), seed(), phase(), net(), addr(), zone();
+int router(struct interface *iface, char **av);
+int dontroute(struct interface *iface, char **av);
+int seed(struct interface *iface, char **av);
+int phase(struct interface *iface, char **av);
+int net(struct interface *iface, char **av);
+int addr(struct interface *iface, char **av);
+int zone(struct interface *iface, char **av);
+int noallmulti(struct interface *iface, char **av);
-static struct param {
+static const struct param {
char *p_name;
- int (*p_func)();
+ int (*p_func)(struct interface *iface, char **av);
} params[] = {
{ "router", router },
{ "dontroute", dontroute },
{ "net", net },
{ "addr", addr },
{ "zone", zone },
+ { "noallmulti", noallmulti }
};
#define ARGV_CHUNK_SIZE 128
#define MAXLINELEN 2048
-char **parseline(const char *line)
+static char **parseline(const char *line)
{
const char *p;
int argc = 0;
return argv;
}
-void freeline( char **argv )
+static void freeline( char **argv )
{
char **tmp = argv;
}
}
-int writeconf( cf )
- char *cf;
+int writeconf(char *cf)
{
struct stat st;
char *path, *p, newpath[ MAXPATHLEN ], line[ MAXLINELEN ];
struct interface *iface;
struct list *l;
int mode = 0644, fd;
+ size_t len;
+ char *zonename;
if ( cf == NULL ) {
path = _PATH_ATALKDCONF;
if ( iface->i_flags & IFACE_DONTROUTE) {
fprintf( newconf, " -dontroute");
}
+#ifdef linux
+ if ( !(iface->i_flags & IFACE_ALLMULTI)) {
+ fprintf( newconf, " -noallmulti");
+ }
+#endif
fprintf( newconf, " -phase %d",
( iface->i_flags & IFACE_PHASE1 ) ? 1 : 2 );
ntohs( iface->i_addr.sat_addr.s_net ),
iface->i_addr.sat_addr.s_node );
for ( l = iface->i_rt->rt_zt; l; l = l->l_next ) {
- fprintf( newconf, " -zone \"%.*s\"",
- ((struct ziptab *)l->l_data)->zt_len,
- ((struct ziptab *)l->l_data)->zt_name );
+ /* codepage conversion */
+ if ((size_t)(-1) == (len = convert_string_allocate(CH_MAC, CH_UNIX,
+ ((struct ziptab *)l->l_data)->zt_name,
+ ((struct ziptab *)l->l_data)->zt_len,
+ &zonename)) ) {
+ if ( NULL ==
+ (zonename = strdup(((struct ziptab *)l->l_data)->zt_name))) {
+ LOG(log_error, logtype_atalkd, "malloc: %s", strerror(errno) );
+ return( -1 );
+ }
+ len = ((struct ziptab *)l->l_data)->zt_len;
+ }
+ fprintf( newconf, " -zone \"%.*s\"", (int)len, zonename);
+ free(zonename);
}
fprintf( newconf, "\n" );
* zone for an interface is the first zone encountered for that
* interface.
*/
-int readconf( cf )
- char *cf;
+int readconf(char *cf)
{
struct ifreq ifr;
struct interface *iface, *niface;
char line[ MAXLINELEN ], **argv, *p;
- int i, j, s, cc;
+ unsigned int i, j;
+ int s, cc = 0;
FILE *conf;
if ( cf == NULL ) {
* Check that av[ 0 ] is a valid interface.
* Not possible under sysV.
*/
- strncpy( ifr.ifr_name, argv[ 0 ], sizeof(ifr.ifr_name) );
- ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
+ strlcpy( ifr.ifr_name, argv[ 0 ], sizeof(ifr.ifr_name) );
/* for devices that don't support appletalk */
if ((ioctl(s, SIOCGIFADDR, &ifr) < 0) && (errno == ENODEV)) {
fprintf(stderr, "Can't configure multicast.\n");
goto read_conf_err;
}
+
#endif /* __svr4__ */
if (( niface = newiface( argv[ 0 ] )) == NULL ) {
goto read_conf_err;
}
+#ifdef linux
+ /* Don't set interface to allmulti if it already is, or -noallmulti was given */
+ if ((ifr.ifr_flags & IFF_ALLMULTI))
+ niface->i_flags |= IFACE_WASALLMULTI;
+
+ if ((niface->i_flags & IFACE_ALLMULTI) && !(niface->i_flags & IFACE_WASALLMULTI))
+ ifsetallmulti(ifr.ifr_name, 1);
+#endif
+
if ( interfaces == NULL ) {
interfaces = niface;
} else {
return -1;
}
+int noallmulti( struct interface *iface, char **av _U_)
+{
+ /* Linux specific, no effect on other platforms */
+ iface->i_flags &= !IFACE_ALLMULTI;
+
+ return (1);
+}
+
/*ARGSUSED*/
-int router( iface, av )
- struct interface *iface;
- char **av;
+int router(struct interface *iface, char **av _U_)
{
/* make sure "-router" and "-dontroute" aren't both on the same line. */
if (iface->i_flags & IFACE_DONTROUTE) {
}
/*ARGSUSED*/
-int dontroute( iface, av )
- struct interface *iface;
- char **av;
+int dontroute(struct interface *iface, char **av _U_)
{
/* make sure "-router" and "-dontroute" aren't both on the same line. */
if (iface->i_flags & IFACE_RSEED) {
}
/*ARGSUSED*/
-int seed( iface, av )
- struct interface *iface;
- char **av;
+int seed( struct interface *iface, char **av _U_)
{
/*
* Check to be sure "-seed" is before "-zone". we keep the old
return( 1 );
}
-int phase( iface, av )
- struct interface *iface;
- char **av;
+int phase(struct interface *iface, char **av)
{
int n;
char *pnum;
return( 2 );
}
-int net( iface, av )
- struct interface *iface;
- char **av;
+int net(struct interface *iface, char **av)
{
char *nrange;
char *stop;
return -1;
}
- if (( stop = strchr( nrange, '-' )) != 0 ) {
+ if (( stop = strchr( nrange, '-' )) != NULL ) {
stop++;
}
net = atoi( nrange );
}
if ( iface->i_flags & IFACE_PHASE1 ) {
- if ( stop != 0 ) {
+ if ( stop != NULL ) {
fprintf( stderr, "Phase 1 doesn't use an address range.\n" );
return -1;
}
iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet = htons( net );
} else if ( iface->i_flags & IFACE_PHASE2 ) {
iface->i_rt->rt_firstnet = htons( net );
- if ( stop != 0 ) {
+ if ( stop != NULL ) {
net = atoi( stop );
if ( net < 0 || net >= 0xffff ) {
fprintf( stderr, "Bad network: %d\n", net );
return( 2 );
}
-int addr( iface, av )
- struct interface *iface;
- char **av;
+int addr(struct interface *iface, char **av)
{
if ( av[ 0 ] == NULL ) {
fprintf( stderr, "No address.\n" );
return( 2 );
}
-int zone( iface, av )
- struct interface *iface;
- char **av;
+int zone(struct interface *iface, char **av)
{
struct ziptab *zt;
char *zname;
- if (( zname = av[ 0 ] ) == NULL ) {
+ if ( av[ 0 ] == NULL ) {
fprintf( stderr, "No zone.\n" );
return -1;
}
+ /* codepage conversion */
+ if ((size_t)(-1) == convert_string_allocate(CH_UNIX, CH_MAC, av[0], -1, &zname)) {
+ zname = strdup(av[0]);
+ }
+
/*
* Only process "-zone" if this interface has "-seed". We keep our
* list of configured zones in the interface structure. Then we can
fprintf( stderr, "Must specify net-range before zones.\n" );
return -1;
}
+
if (( zt = newzt( strlen( zname ), zname )) == NULL ) {
perror( "newzt" );
return -1;
iface->i_czt->zt_next = zt;
}
}
+ free(zname);
+
return( 2 );
}
* Get the configuration from the kernel. Only called if there's no
* configuration.
*/
-int getifconf()
+int getifconf(void)
{
struct interface *iface, *niface;
struct ifreq ifr;
start = list = getifacelist();
while (list && *list) {
- strncpy(ifr.ifr_name, *list, sizeof(ifr.ifr_name));
+ strlcpy(ifr.ifr_name, *list, sizeof(ifr.ifr_name));
list++;
if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0)
* the interface structure and have it updated nicely.
*/
-struct interface *newiface( name )
- const char *name;
+struct interface *newiface( const char *name)
{
struct interface *niface;
== NULL ) {
return( NULL );
}
- strncpy( niface->i_name, name, sizeof(niface->i_name));
+ strlcpy( niface->i_name, name, sizeof(niface->i_name));
#ifdef BSD4_4
niface->i_addr.sat_len = sizeof( struct sockaddr_at );
#endif /* BSD4_4 */
niface->i_caddr.sat_len = sizeof( struct sockaddr_at );
#endif /* BSD4_4 */
niface->i_caddr.sat_family = AF_APPLETALK;
+#ifdef linux
+ niface->i_flags = IFACE_ALLMULTI;
+#endif
return( niface );
}
#ifdef __svr4__
-int plumb()
+int plumb(void)
{
struct interface *iface;
- char device[ MAXPATHLEN + 1], *p;
+ char device[ MAXPATHLEN + 1], *p, *t;
int fd, ppa;
+ int digits = 0;
for ( iface = interfaces; iface != NULL; iface = iface->i_next ) {
if ( strcmp( iface->i_name, LOOPIFACE ) == 0 ) {
strcpy( device, "/dev/" );
strcat( device, iface->i_name );
- if (( p = strpbrk( device, "0123456789" )) == NULL ) {
+ for (t = device; *t != '\0' ; ++t) {
+ if (isdigit(*t) == 0) {
+ p = t + 1;
+ }
+ else {
+ digits++;
+ }
+ }
+
+ if (digits == 0) {
LOG(log_error, logtype_atalkd, "plumb: invalid device: %s", device );
return -1;
}
*p = '\0';
if (( fd = open( device, O_RDWR, 0 )) < 0 ) {
- LOG(log_error, logtype_atalkd, "%s: %m", device );
+ LOG(log_error, logtype_atalkd, "%s: %s", device, strerror(errno) );
return -1;
}
if ( ioctl( fd, I_PUSH, "ddp" ) < 0 ) {
- LOG(log_error, logtype_atalkd, "I_PUSH: %m" );
+ LOG(log_error, logtype_atalkd, "I_PUSH: %s", strerror(errno) );
close(fd);
return -1;
}
if ( ioctl( fd, IF_UNITSEL, ppa ) < 0 ) {
- LOG(log_error, logtype_atalkd, "IF_UNITSEL: %m" );
+ LOG(log_error, logtype_atalkd, "IF_UNITSEL: %s", strerror(errno) );
close(fd);
return -1;
}
}
LOG(log_info, logtype_atalkd, "plumbed %s%d", device, ppa );
+
+ close(fd);
}
return( 0 );