コード例 #1
0
static int ioctl_set_pvc(ITF *itf,uint32_t ip,struct sockaddr_atmpvc *addr,
  const struct atm_qos *qos,int sndbuf,int flags)
{
    ENTRY *entry;
    VCC *vcc;
    int fd,result;

    if (lookup_ip(itf,ip)) return -EEXIST; 
    if ((fd = connect_vcc((struct sockaddr *) addr,qos,sndbuf,0)) < 0)
	return fd;
    if ((result = set_ip(fd,ip)) < 0) {
	do_close(fd);
	return result;
    }
    if (flags & ATF_NULL) {
	if ((result = set_encap(fd,0)) < 0) return result;
	flags |= ATF_PERM;
    }
    entry = alloc_entry(0);
    entry->state = as_valid;
    entry->ip = ip;
    entry->qos = *qos;
    entry->sndbuf = sndbuf;
    entry->flags = flags;
    entry->itf = itf;
    vcc = alloc_t(VCC);
    vcc->active = 1;
    vcc->connecting = 0;
    vcc->fd = fd;
    vcc->entry = entry;
    if (!(flags & ATF_PERM)) START_TIMER(entry,CREVAL);
    Q_INSERT_HEAD(entry->vccs,vcc);
    Q_INSERT_HEAD(itf->table,entry);
    return 0;
}
コード例 #2
0
static int ioctl_set_svc(ITF *itf,uint32_t ip,struct sockaddr_atmsvc *addr,
  const struct atm_qos *qos,int sndbuf,int flags)
{
    ENTRY *entry;

    if (flags & ATF_ARPSRV) flags |= ATF_PERM;
    if (lookup_ip(itf,ip)) return -EEXIST;
    entry = alloc_entry(1);
    entry->state = as_valid;
    entry->ip = ip;
    entry->addr = alloc_t(struct sockaddr_atmsvc);
    *entry->addr = *addr;
    entry->qos = *qos;
    entry->sndbuf = sndbuf;
    entry->flags = flags;
    if (!(flags & ATF_PERM) || (flags & ATF_ARPSRV)) {
	if (itf->arp_srv) START_TIMER(entry,CREVAL);
	else START_TIMER(entry,SREVAL);
    }
    entry->itf = itf;
    Q_INSERT_HEAD(itf->table,entry);
    if (!(flags & ATF_ARPSRV)) return 0;
    entry->state = as_invalid;
    itf->arp_srv = entry;
    (void) want_arp_srv(itf);
    return 0;
}
コード例 #3
0
static int resolve(ITF *itf,uint32_t ip,ENTRY **entry,int want_vc)
{
    *entry = lookup_ip(itf,ip);
    if ((!*entry || (*entry)->state != as_valid) && !itf->arp_srv)
	return -1; /* bad luck - no ARP server when we need one */
    if (*entry) {
	if (want_vc) (*entry)->flags &= ~ATF_NOVC;
	switch ((*entry)->state) {
	    case as_resolv:
		return 1; /* somebody else is already taking care of that */
	    case as_valid:
		if (!(*entry)->vccs && !((*entry)->flags & ATF_NOVC))
		    connect_me(*entry);
		return 0;
	    case as_invalid:
		if ((*entry)->svc && (*entry)->itf && (*entry)->itf->arp_srv &&
		    !((*entry)->flags & ATF_ARPSRV)) break;
		return -1;
	    default:
		diag(COMPONENT,DIAG_FATAL,"bad state %d",(*entry)->state);
	}
    }
    else {
	*entry = alloc_entry(1);
	(*entry)->flags = ATF_PUBL | (want_vc ? 0 : ATF_NOVC);
	(*entry)->ip = ip;
	(*entry)->itf = itf;
	Q_INSERT_HEAD(itf->table,*entry);
	(*entry)->qos = itf->qos;
    }
    revalidate(*entry);
    return 1;
}
コード例 #4
0
ファイル: createtree.c プロジェクト: CuiMingFu/zumastor
static int
cr_newsymlink(nameset_entry_t parent)
{
	int weight = (*cr_l_weights)();
	struct cr_rec *l;

	if ((l = malloc(sizeof(struct cr_rec))) == NULL) {
		report_perror(FATAL, "malloc error");
		return -1;
	}
	bzero(l, sizeof(struct cr_rec));

	if ((l->nse = nameset_alloc(parent, NFLNK, weight)) == NULL) {
		report_error(FATAL, "nameset_alloc error");
		free(l);
		return -1;
	}
	if (nameset_getfname(l->nse, l->name, sizeof(l->name)) < 0) {
		report_error(FATAL, "nameset_getfname error");
		free(l);
		return -1;
	}
	l->parent_nse = parent;

	Q_INSERT_HEAD(&cr_worklist, l, link);
	return 0;
}
コード例 #5
0
ファイル: createtree.c プロジェクト: CuiMingFu/zumastor
static int
cr_newfile(nameset_entry_t parent)
{
	int weight = (*cr_f_weights)();
	struct cr_rec *f;

	if ((f = malloc(sizeof(struct cr_rec))) == NULL) {
		report_perror(FATAL, "malloc error");
		return -1;
	}
	bzero(f, sizeof(struct cr_rec));

	if ((f->nse = nameset_alloc(parent, NFREG, weight)) == NULL) {
		report_error(FATAL, "nameset_alloc error");
		free(f);
		return -1;
	}
	if (nameset_getfname(f->nse, f->name, sizeof(f->name)) < 0) {
		report_error(FATAL, "nameset_getfname error");
		free(f);
		return -1;
	}
	f->parent_nse = parent;

	f->size = (*cr_f_sizes)();

	f->nse->size = f->size; /* eventually */

	Q_INSERT_HEAD(&cr_worklist, f, link);
	return 0;
}
コード例 #6
0
ファイル: createtree.c プロジェクト: CuiMingFu/zumastor
static void
cr_symlink_callback(void *arg, struct nfsmsg *reply, u_int32_t xid)
{
	struct cr_rec *l = (struct cr_rec *)arg;
	struct symlink_res *res = reply ? &reply->u.symlink_res : NULL;

	assert(l->nse->type == NFLNK);
	assert(l->symlink_done == 0);

	if (reply == NULL) {
		report_error(NONFATAL, "cr_symlink cancelled");
		nameset_dele(l->nse);
		free(arg);
		return;
	}
	assert(reply->direction == REPLY);
	if (res->status != NFS_OK) {
		report_error(NONFATAL, "cr_symlink error %d: %s", 
			     res->status, nfs_errstr(res->status));
		nameset_dele(l->nse);
		free(arg);
		return;
	}
	assert(res->optfh.present);
	assert(*((u_int64_t *)res->optfh.fh.data) != 0);
	nameset_setfh(l->nse, res->optfh.fh.data, res->optfh.fh.len);

	l->symlink_done = 1;
	Q_INSERT_HEAD(&cr_worklist, l, link);
}
コード例 #7
0
ファイル: createtree.c プロジェクト: CuiMingFu/zumastor
static void
cr_write_callback(void *arg, struct nfsmsg *reply, u_int32_t xid)
{
	struct cr_rec *f = (struct cr_rec *)arg;
	struct write_res *res = reply ? &reply->u.write_res : NULL;

	assert(f->nse->type == NFREG);
	assert(f->create_done == 1);

	if (reply == NULL) {
		report_error(NONFATAL, "cr_write cancelled");
		free(arg);
		return;
	}
	assert(reply->direction == REPLY);
	if (res->status != NFS_OK) {
#ifdef EXTRA_OUTPUT
		report_error(NONFATAL, "cr_write error %d: %s", 
			     res->status, nfs_errstr(res->status));
#endif
		free(arg);
		return;
	}
	f->size_done += res->count;

	if (res->wcc_data.after.present &&
	    res->wcc_data.after.fattr.fa_size != f->size_done) {
		report_error(NONFATAL, "cr_write response with bad size (got %d, expected %d)",
			     (int)res->wcc_data.after.fattr.fa_size,
			     f->size_done);
	}

	Q_INSERT_HEAD(&cr_worklist, f, link);
}
コード例 #8
0
static void connect_me(ENTRY *entry)
{
    VCC *vcc;
    int fd;

    assert(entry->addr->sas_family == AF_ATMSVC);
    if ((fd = connect_vcc((struct sockaddr *) entry->addr,&entry->qos,
      entry->sndbuf,CLIP_DEFAULT_IDLETIMER)) < 0) return;
    vcc = alloc_t(VCC);
    vcc->active = 1;
    vcc->connecting = 1;
    vcc->fd = fd;
    vcc->entry = entry;
    Q_INSERT_HEAD(entry->vccs,vcc);
}
コード例 #9
0
static int want_arp_srv(const ITF *itf)
{
    VCC *vcc;
    int fd;

    if (!itf->arp_srv) return -1;
    for (vcc = itf->arp_srv->vccs; vcc; vcc = vcc->next)
	if (!vcc->connecting) return 1;
    if (itf->arp_srv->vccs) return 0;
    if ((fd = connect_vcc((struct sockaddr *) itf->arp_srv->addr,
      &itf->arp_srv->qos,itf->arp_srv->sndbuf,CLIP_DEFAULT_IDLETIMER)) < 0)
	return 0;
    vcc = alloc_t(VCC);
    vcc->active = 1;
    vcc->connecting = 1;
    vcc->fd = fd;
    vcc->entry = itf->arp_srv;
    Q_INSERT_HEAD(itf->arp_srv->vccs,vcc);
    return 0;
}
コード例 #10
0
ファイル: createtree.c プロジェクト: CuiMingFu/zumastor
static void
cr_mkdir_callback(void *arg, struct nfsmsg *reply, u_int32_t xid)
{
	struct cr_rec *d = (struct cr_rec *)arg;
	struct mkdir_res *res = reply ? &reply->u.mkdir_res : NULL;

	assert(d->nse->type == NFDIR);

	if (reply == NULL) {
		report_error(NONFATAL, "cr_mkdir cancelled");
		nameset_dele(d->nse);
		free(arg);
		return;
	}
	assert(reply->direction == REPLY);
	if (res->status != NFS_OK) {
		
		/*
		 * special case this common error.
		 */
		if (res->status == NFSERR_EXIST) {
			report_error(NONFATAL, "mkdir returned NFSERR_EXIST.\n"
				     "this will happen if you are re-running"
				     "fstress without first deleting the old"
				     "fstress created files");
		}
		
		report_error(FATAL, "cr_mkdir error %d: %s", 
			     res->status, nfs_errstr(res->status));
		nameset_dele(d->nse);
		free(arg);
		return;
	}
	assert(res->optfh.present);
	assert(*((u_int64_t *)res->optfh.fh.data) != 0);
	nameset_setfh(d->nse, res->optfh.fh.data, res->optfh.fh.len);

	assert(d->mkdir_done == 0);
	d->mkdir_done = 1;
	Q_INSERT_HEAD(&cr_worklist, d, link);
}
コード例 #11
0
ファイル: io.c プロジェクト: ebichu/dd-wrt
static void accept_new(void)
{
    char buffer[MAX_ATM_ADDR_LEN+1];
    struct sockaddr_atmsvc addr;
    struct atm_qos qos;
    ENTRY *entry;
    VCC *vcc;
    int fd,error;
    socklen_t len,size;

    len = sizeof(addr);
    if ((fd = accept(incoming,(struct sockaddr *) &addr,&len)) < 0) {
	error = errno;
	diag(COMPONENT,DIAG_ERROR,"accept: %s",strerror(errno));
	if (error == EUNATCH) {
	    diag(COMPONENT,DIAG_WARN,"disabling SVCs");
	    (void) close(incoming);
	    incoming = -1;
	}
	return;
    }
    /* the following code probably belongs to arp.c ... */
    if (atm2text(buffer,MAX_ATM_ADDR_LEN+1,(struct sockaddr *) &addr,pretty) <
      0) strcpy(buffer,"<atm2text error>");
    diag(COMPONENT,DIAG_DEBUG,"Incoming call from %s",buffer);
    size = sizeof(qos);
    if (getsockopt(fd,SOL_ATM,SO_ATMQOS,&qos,&size) < 0)
	diag(COMPONENT,DIAG_FATAL,"getsockopt SO_ATMQOS: %s",strerror(errno));
    if (size != sizeof(qos))
	diag(COMPONENT,DIAG_FATAL,"SO_ATMQOS: size %d != %d",size,sizeof(qos));
    if (ioctl(fd,ATMARP_MKIP,qos.txtp.traffic_class == ATM_NONE ? 0 :
      CLIP_DEFAULT_IDLETIMER) < 0) {
        diag(COMPONENT,DIAG_ERROR,"ioctl ATMARP_MKIP: %s",strerror(errno));
        (void) do_close(fd);
        return;
    }
    vcc = alloc_t(VCC);
    vcc->active = 0;
    vcc->connecting = 0;
    vcc->fd = fd;
    if (qos.txtp.traffic_class == ATM_NONE) {
	vcc->entry = NULL;
	incoming_unidirectional(vcc);
	Q_INSERT_HEAD(unidirectional_vccs,vcc);
	return;
    }
    if (merge) {
	ITF *itf;

	for (itf = itfs; itf; itf = itf->next) {
	    entry = lookup_addr(itf,&addr);
	    if (entry) {
		vcc->entry = entry;
		Q_INSERT_HEAD(entry->vccs,vcc);
		if (entry->state == as_valid) {
		    if (set_ip(vcc->fd,entry->ip) < 0) {
			diag(COMPONENT,DIAG_ERROR,"set_ip: %s",
			  strerror(errno));
			disconnect_vcc(vcc);
		    }
		    else set_sndbuf(vcc);
		}
		return;
	    }
	}
    }
    entry = alloc_entry(1);
    entry->state = as_invalid;
    entry->addr = alloc_t(struct sockaddr_atmsvc);
    *entry->addr = addr;
    entry->flags = ATF_PUBL;
    Q_INSERT_HEAD(unknown_incoming,entry);
    vcc->entry = entry;
    Q_INSERT_HEAD(entry->vccs,vcc);
    incoming_call(vcc);
}
コード例 #12
0
static int learn(VCC *vcc,uint32_t ip,struct sockaddr_atmsvc *addr)
{
    ENTRY *entry;
    ITF *itf;
    VCC *walk,*next;
    unsigned char *ipp;
    int result = 0;

    if (!ip) return 0;
    ipp = (unsigned char *) &ip;
    itf = lookup_itf_by_ip(ip);
    if (!itf) {
	diag(COMPONENT,DIAG_ERROR,"got unroutable IP address %d.%d.%d.%d",
	  ipp[0],ipp[1],ipp[2],ipp[3]);
	return 0;
    }
    entry = lookup_ip(itf,ip);
    assert(!vcc || vcc->entry);
    /*
     * If the entry on which we received the update isn't dangling but it
     * doesn't correspond to the one with the address, ...
     */
    if (entry && vcc && vcc->entry->itf && entry != vcc->entry) {
	diag(COMPONENT,DIAG_DEBUG,"collision on %d.%d.%d.%d",ipp[0],ipp[1],
	  ipp[2],ipp[3]);
	return 0;
    }
    /*
     * If the entry on which we received the update is dangling and we found
     * an entry that already describes that IP address, ...
     */
    if (entry && vcc && !vcc->entry->itf) {
	if (!entry->svc) {
	    diag(COMPONENT,DIAG_ERROR,"attempt to overwrite PVC for IP "
	      "%d.%d.%d.%d",ipp[0],ipp[1],ipp[2],ipp[3]);
	    return 0;
	}
	STOP_TIMER(vcc->entry);
	Q_REMOVE(unknown_incoming,vcc->entry);
	free(vcc->entry);
	vcc->entry = entry;
	Q_INSERT_HEAD(entry->vccs,vcc);
	set_sndbuf(vcc);
	entry->flags &= ~ATF_NOVC;
	assert(!vcc->connecting);
	if (set_ip(vcc->fd,ip) < 0) {
	    diag(COMPONENT,DIAG_ERROR,"set_ip: %s",strerror(errno));
	    disconnect_vcc(vcc);
	    vcc = NULL;
	    result = -1;
	}
    }
    /*
     * If we still don't have an entry, we try to use the entry that already
     * belongs to the VCC (InARP), or we create a new one (ARP).
     */
    if (!entry) {
	if (vcc) {
	    entry = vcc->entry;
	    if (!entry->itf) {
		Q_REMOVE(unknown_incoming,entry);
		entry->sndbuf = itf->sndbuf;
		set_sndbuf(vcc);
	    }
	    else if (entry->ip && entry->ip != ip && (entry->flags & ATF_PERM)
		  && !(entry->flags & ATF_ARPSRV)) {
		    diag(COMPONENT,DIAG_ERROR,"ignoring attempt to change IP "
		      "address of permanent entry (to %d.%d.%d.%d)",ipp[0],
		      ipp[1],ipp[2],ipp[3]);
		    return result;
		}
	}
	else {
	    entry = alloc_entry(1);
	    entry->flags = ATF_PUBL;
	}
    }
    if (!atmsvc_addr_in_use(*addr)) addr = NULL;
    if (entry->addr && addr && (entry->flags & ATF_PERM) &&
      !atm_equal((struct sockaddr *) entry->addr,(struct sockaddr *) addr,0,0))
      {
	diag(COMPONENT,DIAG_ERROR,"ignoring attempt to change ATM address of "
	  "permanent entry");
	return result;
    }
    if (entry->state == as_valid && entry->ip == ip && (!addr || (entry->addr
      && atm_equal((struct sockaddr *) entry->addr,(struct sockaddr *) addr,0,
      0)))) return result; /* no news */
    STOP_TIMER(entry);
    if (entry->ip != ip) send_notifications(entry,0);
    entry->ip = ip;
    if (!entry->itf) {
	entry->itf = itf;
	/* @@@
	 * Need to fix this is in case we allow entries without a valid IP
	 * address but with a pre-set QOS, e.g. a VC on a given PVC with an
	 * unknown remote end.
	 */
	entry->qos = entry->itf->qos;
	adjust_qos(entry->itf,&entry->qos,0);
	Q_INSERT_HEAD(itf->table,entry);
    }
    if (entry->itf != itf)
	diag(COMPONENT,DIAG_ERROR,"interesting, interface has changed ... "
	  "(%d -> %d)",entry->itf->number,itf->number);
    if (addr) {
	if (!entry->addr) entry->addr = alloc(sizeof(*addr));
	*entry->addr = *addr;
	if (merge) {
	    ENTRY *incoming;

	    while ((incoming = lookup_incoming(addr))) {
		STOP_TIMER(incoming);
		Q_REMOVE(unknown_incoming,incoming);
		incoming->vccs->entry = entry;
		Q_INSERT_HEAD(entry->vccs,incoming->vccs);
		set_sndbuf(incoming->vccs);
		free(incoming);
	    }
	}
    }
    for (walk = entry->vccs; walk; walk = next) {
	next = walk->next;
	if (!walk->connecting)
	    if (set_ip(walk->fd,ip) < 0) {
		diag(COMPONENT,DIAG_ERROR,"set_ip: %s",strerror(errno));
		disconnect_vcc(walk);
		if (walk == vcc) result = -1;
	    }
    }
    if (entry->state != as_valid) {
	if (!entry->vccs && itf->arp_srv && !(entry->flags & ATF_NOVC))
	    connect_me(entry);
	send_notifications(entry,1);
    }
    if ((entry->flags & ATF_ARPSRV) || !(entry->flags & ATF_PERM)) {
	if (entry->itf->arp_srv) START_TIMER(entry,CREVAL);
	else START_TIMER(entry,SREVAL);
    }
    entry->state = as_valid;
    return result;
}
コード例 #13
0
ファイル: createtree.c プロジェクト: CuiMingFu/zumastor
static int
cr_newdir(nameset_entry_t parent, int maxdepth)
{
	int weight = (*cr_d_weights)();
	struct cr_rec *d;

	if ((d = malloc(sizeof(struct cr_rec))) == NULL) {
		report_perror(FATAL, "malloc error");
		return -1;
	}
	bzero(d, sizeof(struct cr_rec));

	if ((d->nse = nameset_alloc(parent, NFDIR, weight)) == NULL) {
		report_error(FATAL, "nameset_alloc error");
		free(d);
		return -1;
	}
	if (nameset_getfname(d->nse, d->name, sizeof(d->name)) < 0) {
		report_error(FATAL, "nameset_getfname error");
		free(d);
		return -1;
	}
	d->parent_nse = parent;
	d->maxdepth = maxdepth - 1;

	d->subdirs = (*cr_d_cnts)();
	d->subfiles = (*cr_f_cnts)();
	d->subsymlinks = (*cr_l_cnts)();

	/*
	 * if count is negative, scale it according to load level.
	 */
	if (d->subdirs < 0) {
		d->subdirs = -(d->subdirs) * cr_scale;
	}
	if (d->subfiles < 0) {
		d->subfiles = -(d->subfiles) * cr_scale;
	}
	if (d->subsymlinks < 0) {
		d->subsymlinks = -(d->subsymlinks) * cr_scale;
	}

	/*
	 * prune things.  first, enforce the max dirtree depth.
	 * then, enforce limits on dirs, files, and symlinks.
	 */
	if (d->maxdepth <= 0) {
		d->subdirs = 0;
	}
	if (cr_d_max != -1) {
		if (d->subdirs > cr_d_max) {
			d->subdirs = cr_d_max;
		}
		cr_d_max -= d->subdirs;
	}
	if (cr_f_max != -1) {
		if (d->subfiles > cr_f_max) {
			d->subfiles = cr_f_max;
		}
		cr_f_max -= d->subfiles;
	}
	if (cr_l_max != -1) {
		if (d->subsymlinks > cr_l_max) {
			d->subsymlinks = cr_l_max;
		}
		cr_l_max -= d->subsymlinks;
	}

	d->nse->size = d->subdirs + d->subfiles; /* eventually */

	Q_INSERT_HEAD(&cr_worklist, d, link);
	return 0;
}