#include <stdio.h>
#include <unistd.h>
#include <mach/boolean.h>
#include <sys/errno.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/sockio.h>
#include <net/if.h>
#include <netat/appletalk.h>
#include <netat/at_var.h>
#include <netat/nbp.h>
#include <AppleTalk/at_proto.h>
#define SET_ERRNO(e) errno = e
#define IFR_NEXT(ifr) \
((struct ifreq *) ((char *) (ifr) + sizeof(*(ifr)) + \
MAX(0, (int) (ifr)->ifr_addr.sa_len - (int) sizeof((ifr)->ifr_addr))))
#define MAX_IF 16
int nbp_reg_lookup(entity, retry)
at_entity_t *entity;
at_retry_t *retry;
{
int i, s, got, cnt = 1;
at_state_t global_state;
at_nbptuple_t tuple;
static at_entity_t entity_copy[IF_TOTAL_MAX];
SET_ERRNO(0);
entity_copy[0] = *entity;
if ((s = socket(AF_APPLETALK, SOCK_RAW, 0)) < 0)
return(-1);
if (ioctl(s, AIOCGETSTATE, (caddr_t)&global_state)) {
(void)close(s);
return(-1);
}
if ((global_state.flags & AT_ST_MULTIHOME) && (entity->zone.str[0] == '*'))
{
struct ifconf ifc;
struct ifreq *ifrbuf = NULL, *ifr;
at_if_cfg_t cfg;
int size = sizeof(struct ifreq) * MAX_IF;
while (1) {
if (ifrbuf != NULL)
ifrbuf = (struct ifreq *)realloc(ifrbuf, size);
else
ifrbuf = (struct ifreq *)malloc(size);
ifc.ifc_req = ifrbuf;
ifc.ifc_len = size;
if (ioctl(s, SIOCGIFCONF, &ifc) < 0 || ifc.ifc_len <= 0) {
fprintf(stderr, "nbp_reg_lookup: SIOCGIFCONF error");
(void)close(s);
if (ifrbuf)
free(ifrbuf);
return(-1);
}
if ((ifc.ifc_len + sizeof(struct ifreq)) < size)
break;
size *= 2;
}
for (ifr = (struct ifreq *) ifc.ifc_buf;
(char *) ifr < &ifc.ifc_buf[ifc.ifc_len];
ifr = IFR_NEXT(ifr)) {
unsigned char *p, c;
if (ifr->ifr_addr.sa_family != AF_APPLETALK)
continue;
if (*ifr->ifr_name == '\0')
continue;
p = &ifr->ifr_name[strlen(ifr->ifr_name)-1];
if ((c = *p) > '0'+9)
sprintf(p, "%d", c-'0');
strcpy(cfg.ifr_name, ifr->ifr_name);
if (ioctl(s, AIOCGETIFCFG, (caddr_t)&cfg) < 0)
continue;
if (cfg.zonename.len < NBP_NVE_STR_SIZE)
cfg.zonename.str[cfg.zonename.len] = '\0';
if (cnt)
entity_copy[cnt] = entity_copy[0];
entity_copy[cnt++].zone = cfg.zonename;
}
if(!cnt) {
fprintf(stderr,"nbp_reg_lookup: no local zones\n");
(void)close(s);
SET_ERRNO(ENOENT);
return(-1);
}
}
(void)close(s);
for (i = 0; i < cnt; i++) {
#ifdef APPLETALK_DEBUG
entity_copy[i].object.str[entity_copy[i].object.len] = '\0';
entity_copy[i].type.str[entity_copy[i].type.len] = '\0';
entity_copy[i].zone.str[entity_copy[i].zone.len] = '\0';
printf("entity %d = %s|%s|%s\n", i, entity_copy[i].object.str,
entity_copy[i].type.str, entity_copy[i].zone.str);
#endif
SET_ERRNO(0);
if ((got = nbp_lookup(&entity_copy[i], &tuple, 1, retry)) < 0) {
SET_ERRNO(EAGAIN);
return(-1);
}
if (got > 0) {
SET_ERRNO(EADDRNOTAVAIL);
return(1);
}
}
return(0);
}
int nbp_register(entity, fd, retry)
at_entity_t *entity;
int fd;
at_retry_t *retry;
{
int if_id;
ddp_addr_t ddp_addr;
at_nbp_reg_t reg;
if (fd < 0) {
SET_ERRNO(EBADF);
return (-1);
}
if (ddp_config(fd, &ddp_addr) < 0)
return (-1);
reg.addr.net = 0;
reg.addr.node = 0;
reg.addr.socket = ddp_addr.inet.socket;
reg.ddptype = ddp_addr.ddptype;
if (nbp_iswild(entity)) {
fprintf(stderr,"nbp_register: object and type cannot be wild\n");
SET_ERRNO(EINVAL);
return (-1);
}
if (nbp_reg_lookup(entity, retry))
return (-1);
reg.name = *entity;
if ((if_id = socket(AF_APPLETALK, SOCK_RAW, 0)) < 0)
return(-1);
if ((ioctl(if_id, AIOCNBPREG, (caddr_t)®)) < 0) {
(void)close(if_id);
return(-1);
}
(void)close(if_id);
return (0);
}