freebsd-dev/sys/netatm/uni/unisig_util.c
1999-08-28 01:08:13 +00:00

392 lines
7.5 KiB
C

/*
*
* ===================================
* HARP | Host ATM Research Platform
* ===================================
*
*
* This Host ATM Research Platform ("HARP") file (the "Software") is
* made available by Network Computing Services, Inc. ("NetworkCS")
* "AS IS". NetworkCS does not provide maintenance, improvements or
* support of any kind.
*
* NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
* INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
* SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
* In no event shall NetworkCS be responsible for any damages, including
* but not limited to consequential damages, arising from or relating to
* any use of the Software or related support.
*
* Copyright 1994-1998 Network Computing Services, Inc.
*
* Copies of this Software may be made, however, the above copyright
* notice must be reproduced on all copies.
*
* @(#) $FreeBSD$
*
*/
/*
* ATM Forum UNI 3.0/3.1 Signalling Manager
* ----------------------------------------
*
* Protocol processing module
*
*/
#include <netatm/kern_include.h>
#include <netatm/uni/unisig.h>
#include <netatm/uni/unisig_var.h>
#include <netatm/uni/unisig_msg.h>
#ifndef lint
__RCSID("@(#) $FreeBSD$");
#endif
/*
* Free a UNISIG signalling message
*
* Free the passed message and any IEs that are attached to it
*
* Arguments:
* msg pointer to UNISIG protocol instance
*
* Returns:
* none
*
*/
void
unisig_free_msg(msg)
struct unisig_msg *msg;
{
int i;
struct ie_generic *ie, *ienxt;
ATM_DEBUG1("unisig_free_msg: msg=%p\n", msg);
/*
* First free all the IEs
*/
for (i=0; i<UNI_MSG_IE_CNT; i++) {
ie = msg->msg_ie_vec[i];
while (ie) {
ienxt = ie->ie_next;
atm_free(ie);
ie = ienxt;
}
}
/*
* Finally, free the message structure itself
*/
atm_free(msg);
}
/*
* Verify a VCCB
*
* Search UNISIG's VCCB queue to verify that a VCCB belongs to UNISIG.
*
* Arguments:
* usp pointer to UNISIG protocol instance
* svp pointer to a VCCB
*
* Returns:
* TRUE the VCCB belongs to UNISIG
* FALSE the VCCB doesn't belong to UNISIG
*
*/
int
unisig_verify_vccb(usp, uvp)
struct unisig *usp;
struct unisig_vccb *uvp;
{
struct unisig_vccb *utp, *uvnext;
for (utp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
utp; utp = uvnext){
uvnext = Q_NEXT(utp, struct unisig_vccb, uv_sigelem);
if (uvp == utp) {
return(TRUE);
}
}
return(FALSE);
}
/*
* Find a connection
*
* Find a VCCB given the call reference
*
* Arguments:
* usp pointer to UNISIG protocol instance
* cref the call reference to search for
*
* Returns:
* 0 there is no such VCCB
* uvp the address of the VCCB
*
*/
struct unisig_vccb *
unisig_find_conn(usp, cref)
struct unisig *usp;
u_int cref;
{
struct unisig_vccb *uvp, *uvnext;
for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb); uvp;
uvp = uvnext){
uvnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
if (uvp->uv_call_ref == cref)
break;
}
return(uvp);
}
/*
* Find a VCCB
*
* Find a VCCB given the VPI and VCI.
*
* Arguments:
* usp pointer to UNISIG protocol instance
* vpi the VPI to search for
* vci the VCI to search for
* dir the direction of the VCC (VCC_IN, VCC_OUT, or both).
* If dir is set to zero, return the address of any VCCB
* with the given VPI/VCI, regardless of direction.
*
* Returns:
* 0 there is no such VCCB
* uvp the address of the VCCB
*
*/
struct unisig_vccb *
unisig_find_vpvc(usp, vpi, vci, dir)
struct unisig *usp;
int vpi, vci;
u_char dir;
{
struct unisig_vccb *uvp, *uvnext;
for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb); uvp;
uvp = uvnext){
uvnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
if (uvp->uv_vpi == vpi &&
uvp->uv_vci == vci &&
(uvp->uv_type & dir) == dir)
break;
}
return(uvp);
}
/*
* Allocate a call reference value
*
* Arguments:
* usp pointer to UNISIG protocol instance
*
* Returns:
* 0 call reference not available
* cref the call reference value
*
*/
int
unisig_alloc_call_ref(usp)
struct unisig *usp;
{
int cref;
/*
* Get the next call reference value
*/
cref = usp->us_cref;
/*
* Make sure it hasn't got too large
*/
if (cref >= UNI_MSG_CALL_REF_DUMMY) {
/* XXX */
log(LOG_ERR, "uni: call reference limit reached\n");
return(0);
}
/*
* Bump the call reference value
*/
usp->us_cref++;
return(cref);
}
/*
* Print an ATM address
*
* Convert an ATM address into an ASCII string suitable for printing.
*
* Arguments:
* p pointer to an ATM address
*
* Returns:
* the address of a string with the ASCII representation of the
* address. This routine returns the address of a statically-
* allocated buffer, so if repeated calls to this routine are made,
* each call will destroy the result of the previous call.
*
*/
char *
unisig_addr_print(p)
Atm_addr *p;
{
int i;
char *fp, *op, t_buff[16];
u_char *cp;
static char strbuff[256];
static char nf_DCC[] = "0xX.XX.X.XXX.XX.XX.XX.XXXXXX.X";
static char nf_ICD[] = "0xX.XX.X.XXX.XX.XX.XX.XXXXXX.X";
static char nf_E164[] = "0xX.XXXXXXXX.XX.XX.XXXXXX.X";
union {
int w;
char c[4];
} u1, u2;
/*
* Clear the print buffer
*/
KM_ZERO(strbuff, sizeof(strbuff));
/*
* Select appropriate printing format
*/
switch(p->address_format) {
case T_ATM_ENDSYS_ADDR:
/*
* Select format by NSAP type
*/
switch(((Atm_addr_nsap *)p->address)->aan_afi) {
default:
case AFI_DCC:
fp = nf_DCC;
break;
case AFI_ICD:
fp = nf_ICD;
break;
case AFI_E164:
fp = nf_E164;
break;
}
/*
* Loop through the format string, converting the NSAP
* to ASCII
*/
cp = (u_char *) p->address;
op = strbuff;
while (*fp) {
if (*fp == 'X') {
/*
* If format character is an 'X', put a
* two-digit hex representation of the
* NSAP byte in the output buffer
*/
snprintf(t_buff, sizeof(t_buff),
"%x", *cp + 512);
strcpy(op, &t_buff[strlen(t_buff)-2]);
op++; op++;
cp++;
} else {
/*
* If format character isn't an 'X',
* just copy it to the output buffer
*/
*op = *fp;
op++;
}
fp++;
}
break;
case T_ATM_E164_ADDR:
/*
* Print the IA5 characters of the E.164 address
*/
for(i=0; i<p->address_length; i++) {
snprintf(strbuff + strlen(strbuff),
sizeof(strbuff) - strlen(strbuff), "%c",
((Atm_addr_e164 *)p->address)->aae_addr[i]);
}
break;
case T_ATM_SPANS_ADDR:
/*
* Get address into integers
*/
u1.c[0] = ((Atm_addr_spans *)p->address)->aas_addr[0];
u1.c[1] = ((Atm_addr_spans *)p->address)->aas_addr[1];
u1.c[2] = ((Atm_addr_spans *)p->address)->aas_addr[2];
u1.c[3] = ((Atm_addr_spans *)p->address)->aas_addr[3];
u2.c[0] = ((Atm_addr_spans *)p->address)->aas_addr[4];
u2.c[1] = ((Atm_addr_spans *)p->address)->aas_addr[5];
u2.c[2] = ((Atm_addr_spans *)p->address)->aas_addr[6];
u2.c[3] = ((Atm_addr_spans *)p->address)->aas_addr[7];
/*
* Print the address as two words xxxxx.yyyyyyyy
*/
snprintf(strbuff, sizeof(strbuff), "%x.%x", u1.w, u2.w);
break;
case T_ATM_ABSENT:
default:
strcpy(strbuff, "-");
}
return(strbuff);
}
/*
* Print the contents of a message buffer chain
*
* Arguments:
* m pointer to a buffer
*
* Returns:
* none
*
*/
void
unisig_print_mbuf(m)
KBuffer *m;
{
int i;
caddr_t cp;
printf("unisig_print_mbuf:\n");
while (m) {
KB_DATASTART(m, cp, caddr_t);
for (i = 0; i < KB_LEN(m); i++) {
if (i == 0)
printf(" bfr=%p: ", m);
printf("%x ", (u_char)*cp++);
}
printf("<end_bfr>\n");
m = KB_NEXT(m);
}
}