Exemplo n.º 1
0
static struct sockaddr_atmsvc *do_get_local(SIG_ENTITY *sig)
{
    VPCI *vpci;
    LOCAL_ADDR *local;

    for (vpci = sig->vpcis; vpci; vpci = vpci->next)
	for (local = vpci->local_addr; local->state != ls_unused; local++)
	    if (local->state == ls_same && atmsvc_addr_in_use(local->addr))
		return &local->addr;
    return NULL;

}
Exemplo n.º 2
0
SOCKET *lookup_sap(const struct sockaddr_atmsvc *addr,
  const struct atm_sap *sap,const struct atm_qos *qos,
  struct sockaddr_atmsvc *res_addr,struct atm_sap *res_sap,
  struct atm_qos *res_qos,int exact_match)
{
    SOCKET *walk,*wildcard;
    int new_wc;

    new_wc = !atmsvc_addr_in_use(*addr);
    wildcard = NULL;
    for (walk = sockets; walk; walk = walk->next) {
	if (walk->state != ss_listening || !sap_compat(&walk->local,
	  addr,res_addr,&walk->sap,sap,res_sap,&walk->qos,qos,res_qos))
	    continue;
	if (atmsvc_addr_in_use(walk->local)) return walk;
	else if (exact_match) {
		if (new_wc) return walk;
	    }
	    else wildcard = walk;
    }
    return wildcard;
}
Exemplo n.º 3
0
static int query_result(struct atmarp_req *reply)
{
    unsigned char *ipp = (unsigned char *) &reply->ip;
    char buf[MAX_ATM_ADDR_LEN+1];
    int error;

    printf("IP:  %d.%d.%d.%d\n",ipp[0],ipp[1],ipp[2],ipp[3]);
    if (!atmsvc_addr_in_use(reply->addr)) return 0;
    error = atm2text(buf,sizeof(buf),(struct sockaddr *) &reply->addr,
      A2T_PRETTY | A2T_NAME) < 0;
    if (error) strcpy(buf,"<invalid>");
    printf("ATM: %s\n",buf);
    return error ? 1 : 0;
}
Exemplo n.º 4
0
int sap_compat(const struct sockaddr_atmsvc *old_addr,
  const struct sockaddr_atmsvc *new_addr,struct sockaddr_atmsvc *res_addr,
  const struct atm_sap *old_sap,const struct atm_sap *new_sap,
  struct atm_sap *res_sap,const struct atm_qos *old_qos,
  const struct atm_qos *new_qos,struct atm_qos *res_qos)
{
    if (atmsvc_addr_in_use(*old_addr) &&
      !atm_equal((struct sockaddr *) old_addr,(struct sockaddr *) new_addr,0,0))
	return 0;
    if (res_qos) *res_qos = *new_qos;
    if (old_qos->txtp.max_sdu && new_qos->rxtp.max_sdu &&
      old_qos->txtp.max_sdu > new_qos->rxtp.max_sdu) return 0;
    if (new_qos->txtp.max_sdu && old_qos->rxtp.max_sdu &&
      new_qos->txtp.max_sdu > old_qos->rxtp.max_sdu) return 0;
    if (!class_compat(&old_qos->txtp,&new_qos->rxtp) ||
      !class_compat(&new_qos->txtp,&old_qos->rxtp)) return 0;
    if (!sap_equal(old_sap,new_sap,
      SXE_COMPATIBLE | SXE_NEGOTIATION | (res_sap ? SXE_RESULT : 0),res_sap))
	return 0;
    return 1;
}
Exemplo n.º 5
0
static void setup_call(SIG_ENTITY *sig,unsigned long call_ref)
{
    SOCKET *sock,*this,**walk;
    struct sockaddr_atmsvc in_addr;
    struct atm_sap in_sap;
    struct atm_qos in_qos;
    unsigned int problem;
    int i;

    problem = sap_decode(&in_dsc,&in_addr,&in_sap,&in_qos,sig->uni);
    if (problem) {
	send_release_complete(sig,call_ref,IE_PB_CAUSE(problem),
	  IE_PB_IE(problem));
	return;
    }
    if (!atmsvc_addr_in_use(in_addr)) {
	send_release_complete(sig,call_ref,ATM_CV_UNALLOC);
	return;
    }
    if (!allow(&in_addr,ACL_IN)) {
	send_release_complete(sig,call_ref,ATM_CV_REJ_CLIR);
	return;
    }
    this = new_sock(kptr_null);
    this->sig = sig;
    sock = lookup_sap(&in_addr,&in_sap,&in_qos,&this->local,&this->sap,
      &this->qos,0);
    if (!sock) {
	free_sock(this);
	send_release_complete(sig,call_ref,ATM_CV_INCOMP_DEST);
	return;
    }
    this->state = sig->mode == sm_net ? ss_proceeding : ss_indicated;
    this->call_state = cs_in_proc;
    this->call_ref = call_ref;
    if (q_present(&in_dsc,QF_ep_ref))
	this->ep_ref = cvt_ep_ref(sig,q_fetch(&in_dsc,QF_ep_ref));
#ifdef CISCO
    else
#endif
    if (sig->mode == sm_net) {
	int error;

	error = send_call_proceeding(this);
	if (error) {
	    free_sock(this);
	    send_release_complete(sig,call_ref,ATM_CV_NO_CI);
	    return;
	}
    }
    /* if (sock->local) *this->local->sas_addr = sock->local->sas_addr; ??? */
    diag(COMPONENT,DIAG_DEBUG,"AAL type %ld",q_fetch(&in_dsc,QF_aal_type));
    if (sig->mode == sm_user) { /* already set by send_call_proceeding */
	int vpci;

	vpci = q_fetch(&in_dsc,QF_vpi);
	this->pvc.sap_family = AF_ATMPVC;
	this->pvc.sap_addr.itf = get_itf(sig,&vpci);
	this->pvc.sap_addr.vpi = vpci;
	this->pvc.sap_addr.vci = q_fetch(&in_dsc,QF_vci);
    }
    diag(COMPONENT,DIAG_DEBUG,"ITF.VPI.VCI: %d.%d.%d",this->pvc.sap_addr.itf,
      this->pvc.sap_addr.vpi,this->pvc.sap_addr.vci);
    if (q_present(&in_dsc,QF_cgpn)) { /* should handle E.164 too */
	char buffer[MAX_ATM_ADDR_LEN+1];
	int plan;

	plan = q_fetch(&in_dsc,QF_cgpn_plan);
	switch (plan) {
	    case ATM_NP_AEA:
		i = q_read(&in_dsc,QF_cgpn,(void *) this->remote.sas_addr.prv,
		  ATM_ESA_LEN);
		break;
	    case ATM_NP_E164:
		i = q_read(&in_dsc,QF_cgpn,(void *) this->remote.sas_addr.pub,
		  ATM_E164_LEN);
		break;
	    default:
		diag(COMPONENT,DIAG_WARN,"Ignoring cgpn with unrecognized "
		  "numbering plan 0x%x\n",plan);
		i = 0;
	}
	if (i) {
	    this->remote.sas_family = AF_ATMSVC;
	    if (atm2text(buffer,MAX_ATM_ADDR_LEN+1,
	      (struct sockaddr *) &this->remote,pretty) < 0)
		strcpy(buffer,"<invalid address>");
	    diag(COMPONENT,DIAG_DEBUG,"Incoming call from %s",buffer);
	}
    }
    send_kernel(kptr_null,sock->id,as_indicate,0,&this->pvc,&this->remote,
      &in_addr,&this->sap,&this->qos);
    for (walk = &sock->listen; *walk; walk = &(*walk)->listen);
    *walk = this;
    diag(COMPONENT,DIAG_DEBUG,"SE vpi.vci=%d.%d",this->pvc.sap_addr.vpi,
      this->pvc.sap_addr.vci);
}
Exemplo n.º 6
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;
}