#if TPCONS
#ifdef KERNEL
#ifdef ARGO_DEBUG
#define Static
unsigned LAST_CALL_PCB;
#else
#define Static static
#endif
#ifndef SOCK_STREAM
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/errno.h>
#include <sys/ioctl.h>
#include <sys/tsleep.h>
#include <net/if.h>
#include <net/netisr.h>
#include <net/route.h>
#include <netiso/iso_errno.h>
#include <netiso/argo_debug.h>
#include <netiso/tp_trace.h>
#include <netiso/iso.h>
#include <netiso/cons.h>
#include <netiso/iso_pcb.h>
#include <netccitt/x25.h>
#include <netccitt/pk.h>
#include <netccitt/pk_var.h>
#endif
#ifdef ARGO_DEBUG
#define MT_XCONN 0x50
#define MT_XCLOSE 0x51
#define MT_XCONFIRM 0x52
#define MT_XDATA 0x53
#define MT_XHEADER 0x54
#else
#define MT_XCONN MT_DATA
#define MT_XCLOSE MT_DATA
#define MT_XCONFIRM MT_DATA
#define MT_XDATA MT_DATA
#define MT_XHEADER MT_HEADER
#endif
#define DONTCLEAR -1
#define CONS_IFQMAXLEN 5
Static struct protosw *CLNP_proto;
Static struct protosw *TP_proto;
Static struct protosw *X25_proto;
Static int issue_clear_req();
#ifndef PHASEONE
extern struct ifaddr *ifa_ifwithnet();
#endif
extern struct ifaddr *ifa_ifwithaddr();
extern struct isopcb tp_isopcb;
Static int parse_facil(), NSAPtoDTE(), make_partial_x25_packet();
Static int FACILtoNSAP(), DTEtoNSAP();
Static struct pklcd *cons_chan_to_pcb();
#define HIGH_NIBBLE 1
#define LOW_NIBBLE 0
void
nibble_copy(src_octet, src_nibble, dst_octet, dst_nibble, len)
register char *src_octet;
register char *dst_octet;
register unsigned src_nibble;
register unsigned dst_nibble;
int len;
{
register i;
register unsigned dshift, sshift;
IFDEBUG(D_CADDR)
printf("nibble_copy ( 0x%x, 0x%x, 0x%x, 0x%x 0x%x)\n",
src_octet, src_nibble, dst_octet, dst_nibble, len);
ENDDEBUG
#define SHIFT 0x4
dshift = dst_nibble << 2;
sshift = src_nibble << 2;
for (i=0; i<len; i++) {
*dst_octet &= ~(0xf<< dshift);
*dst_octet |= ( 0xf & (*src_octet >> sshift))<< dshift;
dshift ^= SHIFT;
sshift ^= SHIFT;
src_nibble = 1-src_nibble;
dst_nibble = 1-dst_nibble;
src_octet += src_nibble;
dst_octet += dst_nibble;
}
IFDEBUG(D_CADDR)
printf("nibble_copy DONE\n");
ENDDEBUG
}
int
nibble_match( src_octet, src_nibble, dst_octet, dst_nibble, len)
register char *src_octet;
register char *dst_octet;
register unsigned src_nibble;
register unsigned dst_nibble;
int len;
{
register i;
register unsigned dshift, sshift;
u_char nibble_a, nibble_b;
IFDEBUG(D_CADDR)
printf("nibble_match ( 0x%x, 0x%x, 0x%x, 0x%x 0x%x)\n",
src_octet, src_nibble, dst_octet, dst_nibble, len);
ENDDEBUG
#define SHIFT 0x4
dshift = dst_nibble << 2;
sshift = src_nibble << 2;
for (i=0; i<len; i++) {
nibble_b = ((*dst_octet)>>dshift) & 0xf;
nibble_a = ( 0xf & (*src_octet >> sshift));
if (nibble_b != nibble_a)
return 0;
dshift ^= SHIFT;
sshift ^= SHIFT;
src_nibble = 1-src_nibble;
dst_nibble = 1-dst_nibble;
src_octet += src_nibble;
dst_octet += dst_nibble;
}
IFDEBUG(D_CADDR)
printf("nibble_match DONE\n");
ENDDEBUG
return 1;
}
cons_init()
{
int tp_incoming(), clnp_incoming();
CLNP_proto = pffindproto(AF_ISO, ISOPROTO_CLNP, SOCK_DGRAM);
X25_proto = pffindproto(AF_ISO, ISOPROTO_X25, SOCK_STREAM);
TP_proto = pffindproto(AF_ISO, ISOPROTO_TP0, SOCK_SEQPACKET);
IFDEBUG(D_CCONS)
printf("cons_init end : cnlp_proto 0x%x cons proto 0x%x tp proto 0x%x\n",
CLNP_proto, X25_proto, TP_proto);
ENDDEBUG
#ifdef notdef
pk_protolisten(0x81, 0, clnp_incoming);
pk_protolisten(0x82, 0, esis_incoming);
pk_protolisten(0x84, 0, tp8878_A_incoming);
pk_protolisten(0, 0, tp_incoming);
#endif
}
tp_incoming(lcp, m)
struct pklcd *lcp;
register struct mbuf *m;
{
register struct isopcb *isop;
int cons_tpinput();
if (iso_pcballoc((struct socket *)0, &tp_isopcb)) {
pk_close(lcp);
return;
}
isop = tp_isopcb.isop_next;
lcp->lcd_upper = cons_tpinput;
lcp->lcd_upnext = (caddr_t)isop;
lcp->lcd_send(lcp);
isop->isop_chan = (caddr_t)lcp;
isop->isop_laddr = &isop->isop_sladdr;
isop->isop_faddr = &isop->isop_sfaddr;
DTEtoNSAP(isop->isop_laddr, &lcp->lcd_laddr);
DTEtoNSAP(isop->isop_faddr, &lcp->lcd_faddr);
parse_facil(lcp, isop, &(mtod(m, struct x25_packet *)->packet_data),
m->m_pkthdr.len - PKHEADERLN);
}
cons_tpinput(lcp, m0)
struct mbuf *m0;
struct pklcd *lcp;
{
register struct isopcb *isop = (struct isopcb *)lcp->lcd_upnext;
register struct x25_packet *xp;
int cmd, ptype = CLEAR;
if (isop == 0)
return;
if (m0 == 0)
goto dead;
switch(m0->m_type) {
case MT_DATA:
case MT_OOBDATA:
tpcons_input(m0, isop->isop_faddr, isop->isop_laddr, (caddr_t)lcp);
return;
case MT_CONTROL:
switch (ptype = pk_decode(mtod(m0, struct x25_packet *))) {
case RR:
cmd = PRC_CONS_SEND_DONE;
break;
case CALL_ACCEPTED:
if (lcp->lcd_sb.sb_mb)
lcp->lcd_send(lcp);
default:
return;
dead:
case CLEAR:
case CLEAR_CONF:
lcp->lcd_upper = 0;
lcp->lcd_upnext = 0;
isop->isop_chan = 0;
case RESET:
cmd = PRC_ROUTEDEAD;
}
tpcons_ctlinput(cmd, isop->isop_faddr, isop);
if (cmd = PRC_ROUTEDEAD && isop->isop_refcnt == 0)
iso_pcbdetach(isop);
}
}
cons_connect(isop)
register struct isopcb *isop;
{
register struct pklcd *lcp = (struct pklcd *)isop->isop_chan;
register struct mbuf *m;
struct ifaddr *ifa;
int error;
IFDEBUG(D_CCONN)
printf("cons_connect(0x%x): ", isop);
dump_isoaddr(isop->isop_faddr);
printf("myaddr: ");
dump_isoaddr(isop->isop_laddr);
printf("\n" );
ENDDEBUG
NSAPtoDTE(isop->isop_faddr, &lcp->lcd_faddr);
lcp->lcd_upper = cons_tpinput;
lcp->lcd_upnext = (caddr_t)isop;
IFDEBUG(D_CCONN)
printf(
"calling make_partial_x25_packet( 0x%x, 0x%x, 0x%x)\n",
&lcp->lcd_faddr, &lcp->lcd_laddr,
isop->isop_socket->so_proto->pr_protocol);
ENDDEBUG
if ((error = make_partial_x25_packet(isop, lcp, m)) == 0)
error = pk_connect(lcp, &lcp->lcd_faddr);
return error;
}
cons_ctlinput(cmd, sa, copcb)
int cmd;
struct sockaddr *sa;
register struct pklcd *copcb;
{
}
find_error_reason( xp )
register struct x25_packet *xp;
{
extern u_char x25_error_stats[];
int error, cause;
if (xp) {
cause = 4[(char *)xp];
switch (cause) {
case 0x00:
case 0x80:
error = (CONL_ERROR_MASK | cause);
goto done;
case 0x01:
case 0x81:
case 0x09:
case 0x89:
case 0x11:
case 0x91:
case 0x19:
case 0x99:
case 0x21:
case 0xa1:
case 0x29:
case 0xa9:
case 0x39:
case 0xb9:
case 0x03:
case 0x83:
case 0x0b:
case 0x8b:
case 0x13:
case 0x93:
case 0x05:
case 0x85:
case 0x8d:
case 0x0d:
case 0x95:
case 0x15:
error = (CONL_ERROR_MASK | 0x100 | (cause & ~0x80));
goto done;
case 0xc1:
case 0xc3:
error = (CONL_ERROR_MASK | 0x100 | cause);
goto done;
}
}
error = xp->packet_data;
if (error = 0) {
printf("Incoming PKT TYPE 0x%x with reason 0x%x\n",
pk_decode(xp),
cause);
error = E_CO_HLI_DISCA;
}
done:
return error;
}
#endif
#ifdef X25_1984
int cons_use_facils = 1;
#else
int cons_use_facils = 0;
#endif
int cons_use_udata = 1;
Static int
make_partial_x25_packet(isop, lcp)
struct isopcb *isop;
struct pklcd *lcp;
{
u_int proto;
int flag;
caddr_t buf;
register caddr_t ptr;
register int len = 0;
int buflen =0;
caddr_t facil_len;
int oddness = 0;
struct mbuf *m;
IFDEBUG(D_CCONN)
printf("make_partial_x25_packet(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
isop->isop_laddr, isop->isop_faddr, proto, m, flag);
ENDDEBUG
if (cons_use_udata) {
if (isop->isop_x25crud_len > 0) {
bcopy(isop->isop_x25crud, lcp->lcd_faddr.x25_udata,
isop->isop_x25crud_len);
lcp->lcd_faddr.x25_udlen = isop->isop_x25crud_len;
}
}
if (cons_use_facils == 0) {
lcp->lcd_facilities = 0;
return 0;
}
MGETHDR(m, MT_DATA, M_WAITOK);
if (m == 0)
return ENOBUFS;
buf = mtod(m, caddr_t);
ptr = buf;
facil_len = ptr ++;
m->m_len = 0;
pk_build_facilities(m, &lcp->lcd_faddr, 0);
IFDEBUG(D_CADDR)
printf("make_partial calling: ptr 0x%x, len 0x%x\n", ptr,
isop->isop_laddr->siso_addr.isoa_len);
ENDDEBUG
if (cons_use_facils) {
*ptr++ = 0;
*ptr++ = 0x0f;
*ptr = 0xcb;
ptr ++;
ptr ++;
ptr ++;
len = isop->isop_laddr->siso_addr.isoa_len;
bcopy( isop->isop_laddr->siso_data, ptr, len);
*(ptr-2) = len+1;
*(ptr-1) = len<<1;
ptr += len;
IFDEBUG(D_CADDR)
printf("make_partial called: ptr 0x%x, len 0x%x\n", ptr,
isop->isop_faddr->siso_addr.isoa_len);
ENDDEBUG
*ptr = 0xc9;
ptr ++;
ptr ++;
ptr ++;
len = isop->isop_faddr->siso_nlen;
bcopy(isop->isop_faddr->siso_data, ptr, len);
*(ptr-2) = len+1;
*(ptr-1) = len<<1;
ptr += len;
}
*facil_len = ptr - facil_len - 1;
if (*facil_len > MAX_FACILITIES)
return E_CO_PNA_LONG;
buflen = (int)(ptr - buf);
IFDEBUG(D_CDUMP_REQ)
register int i;
printf("ECN_CONNECT DATA buf 0x%x len %d (0x%x)\n",
buf, buflen, buflen);
for( i=0; i < buflen; ) {
printf("+%d: %x %x %x %x %x %x %x %x\n",
i,
*(buf+i), *(buf+i+1), *(buf+i+2), *(buf+i+3),
*(buf+i+4), *(buf+i+5), *(buf+i+6), *(buf+i+7));
i+=8;
}
ENDDEBUG
IFDEBUG(D_CADDR)
printf("make_partial returns buf 0x%x size 0x%x bytes\n",
mtod(m, caddr_t), buflen);
ENDDEBUG
if (buflen > MHLEN)
return E_CO_PNA_LONG;
m->m_pkthdr.len = m->m_len = buflen;
lcp->lcd_facilities = m;
return 0;
}
Static int
NSAPtoDTE(siso, sx25)
register struct sockaddr_iso *siso;
register struct sockaddr_x25 *sx25;
{
int dtelen = -1;
IFDEBUG(D_CADDR)
printf("NSAPtoDTE: nsap: %s\n", clnp_iso_addrp(&siso->siso_addr));
ENDDEBUG
if (siso->siso_data[0] == AFI_37) {
register char *out = sx25->x25_addr;
register char *in = siso->siso_data + 1;
register int nibble;
char *lim = siso->siso_data + siso->siso_nlen;
char *olim = out+15;
int lowNibble = 0;
while (in < lim) {
nibble = ((lowNibble ? *in++ : (*in >> 4)) & 0xf) | 0x30;
lowNibble ^= 1;
if (nibble != 0x3f && out < olim)
*out++ = nibble;
}
dtelen = out - sx25->x25_addr;
*out++ = 0;
} else {
register struct rtentry *rt;
extern struct sockaddr_iso blank_siso;
struct sockaddr_iso nsiso;
nsiso = blank_siso;
bcopy(nsiso.siso_data, siso->siso_data,
nsiso.siso_nlen = siso->siso_nlen);
if (rt = rtalloc1(&nsiso, 1)) {
register struct sockaddr_x25 *sxx =
(struct sockaddr_x25 *)rt->rt_gateway;
register char *in = sxx->x25_addr;
rt->rt_use--;
if (sxx && sxx->x25_family == AF_CCITT) {
bcopy(sx25->x25_addr, sxx->x25_addr, sizeof(sx25->x25_addr));
while (*in++) {}
dtelen = in - sxx->x25_addr;
}
}
}
return dtelen;
}
Static int
FACILtoNSAP(addr, buf)
register u_char *buf;
register struct sockaddr_iso *addr;
{
int len_in_nibbles = *++buf & 0x3f;
u_char buf_len = (len_in_nibbles + 1) >> 1;;
IFDEBUG(D_CADDR)
printf("FACILtoNSAP( 0x%x, 0x%x, 0x%x )\n",
buf, buf_len, addr );
ENDDEBUG
len_in_nibbles = *buf & 0x3f;
switch (*buf++ & 0xc0) {
case 0:
bcopy((caddr_t)buf, addr->siso_data, addr->siso_nlen = buf_len);
break;
case 40:
if (buf_len + addr->siso_nlen > sizeof(addr->siso_addr))
return -1;
bcopy((caddr_t)buf, TSEL(addr), buf_len);
addr->siso_nlen += buf_len;
break;
default:
;
}
return 0;
}
Static
init_siso(siso)
register struct sockaddr_iso *siso;
{
siso->siso_len = sizeof (*siso);
siso->siso_family = AF_ISO;
siso->siso_data[0] = AFI_37;
siso->siso_nlen = 8;
}
Static int
DTEtoNSAP(addr, sx)
struct sockaddr_iso *addr;
struct sockaddr_x25 *sx;
{
register char *in, *out;
register int first;
int pad_tail = 0;
int src_len;
init_siso(addr);
in = sx->x25_addr;
src_len = strlen(in);
addr->siso_nlen = (src_len + 3) / 2;
out = addr->siso_data;
*out++ = 0x37;
if (src_len & 1) {
pad_tail = 0xf;
src_len++;
}
for (first = 0; src_len > 0; src_len--) {
first |= 0xf & *in++;
if (src_len & 1) {
*out++ = first;
first = 0;
}
else first <<= 4;
}
if (pad_tail)
out[-1] |= 0xf;
return 0;
}
Static int
parse_facil(lcp, isop, buf, buf_len)
caddr_t buf;
u_char buf_len;
struct isopcb *isop;
struct pklcd *lcp;
{
register int i;
register u_char *ptr = (u_char *)buf;
u_char *ptr_lim, *facil_lim;
int facil_param_len, facil_len;
IFDEBUG(D_CADDR)
printf("parse_facil(0x%x, 0x%x, 0x%x, 0x%x)\n",
lcp, isop, buf, buf_len);
dump_buf(buf, buf_len);
ENDDEBUG
i = (int)(*ptr >> 4) + (int)(*ptr&0xf);
i++;
ptr += i >> 1;
ptr ++;
facil_len = *ptr++;
facil_lim = ptr + facil_len;
IFDEBUG(D_CADDR)
printf("parse_facils: facil length is 0x%x\n", (int) facil_len);
ENDDEBUG
while (ptr < facil_lim) {
switch (*ptr++) {
case 0xcb:
facil_param_len = FACILtoNSAP(isop->isop_faddr, ptr);
break;
case 0xc9:
facil_param_len = FACILtoNSAP(isop->isop_laddr, ptr);
break;
case 0xca:
case 0xc6:
case 0xc5:
case 0xc2:
case 0xc1:
case 0xc4:
case 0xc3:
facil_param_len = 0;
break;
case 0x0a:
case 0x02:
case 0x03: case 0x47:
case 0x0b:
case 0x01:
case 0x04:
case 0x08:
case 0x00:
facil_param_len = 1;
break;
case 0x42:
case 0x43:
case 0x44:
case 0x41:
case 0x49:
facil_param_len = 2;
break;
default:
printf(
"BOGUS FACILITY CODE facil_lim 0x%x facil_len %d, ptr 0x%x *ptr 0x%x\n",
facil_lim, facil_len, ptr - 1, ptr[-1]);
switch (ptr[-1] & 0xc0) {
case 0x00: facil_param_len = 1; break;
case 0x40: facil_param_len = 2; break;
case 0x80: facil_param_len = 3; break;
case 0xc0: facil_param_len = 0; break;
}
}
if (facil_param_len == -1)
return E_CO_REG_ICDA;
if (facil_param_len == 0)
facil_param_len = (int)*ptr++;
ptr += facil_param_len;
}
return 0;
}
#endif