xref: /csrg-svn/sys/netccitt/pk_usrreq.c (revision 57024)
141709Ssklower /*
241709Ssklower  * Copyright (c) University of British Columbia, 1984
3*57024Ssklower  * Copyright (C) Computer Science Department IV,
4*57024Ssklower  * 		 University of Erlangen-Nuremberg, Germany, 1992
5*57024Ssklower  * Copyright (c) 1991, 1992  The Regents of the University of California.
641709Ssklower  * All rights reserved.
741709Ssklower  *
8*57024Ssklower  * This code is derived from software contributed to Berkeley by the
9*57024Ssklower  * Laboratory for Computation Vision and the Computer Science Department
10*57024Ssklower  * of the the University of British Columbia and the Computer Science
11*57024Ssklower  * Department (IV) of the University of Erlangen-Nuremberg, Germany.
1241709Ssklower  *
1341709Ssklower  * %sccs.include.redist.c%
1441709Ssklower  *
15*57024Ssklower  *	@(#)pk_usrreq.c	7.18 (Berkeley) 12/08/92
1641709Ssklower  */
1741595Ssklower 
1856530Sbostic #include <sys/param.h>
1956530Sbostic #include <sys/systm.h>
2056530Sbostic #include <sys/mbuf.h>
2156530Sbostic #include <sys/socket.h>
2256530Sbostic #include <sys/socketvar.h>
2356530Sbostic #include <sys/protosw.h>
2456530Sbostic #include <sys/errno.h>
2556530Sbostic #include <sys/ioctl.h>
2656530Sbostic #include <sys/stat.h>
2741595Ssklower 
2856530Sbostic #include <net/if.h>
2956530Sbostic #include <net/route.h>
3041595Ssklower 
3156530Sbostic #include <netccitt/x25.h>
3256530Sbostic #include <netccitt/pk.h>
3356530Sbostic #include <netccitt/pk_var.h>
3442140Ssklower 
35*57024Ssklower static old_to_new();
36*57024Ssklower static new_to_old();
3741595Ssklower /*
3841595Ssklower  *
3941595Ssklower  *  X.25 Packet level protocol interface to socket abstraction.
4041595Ssklower  *
4141595Ssklower  *  Process an X.25 user request on a logical channel.  If this is a send
4241595Ssklower  *  request then m is the mbuf chain of the send data. If this is a timer
4341595Ssklower  *  expiration (called from the software clock routine) them timertype is
4441595Ssklower  *  the particular timer.
4541595Ssklower  *
4641595Ssklower  */
4741595Ssklower 
4841936Ssklower pk_usrreq (so, req, m, nam, control)
4941595Ssklower struct socket *so;
5041595Ssklower int req;
5141595Ssklower register struct mbuf *m, *nam;
5241936Ssklower struct mbuf *control;
5341595Ssklower {
5441595Ssklower 	register struct pklcd *lcp = (struct pklcd *) so -> so_pcb;
5541936Ssklower 	register int error = 0;
5641595Ssklower 
5741936Ssklower 	if (req == PRU_CONTROL)
5847261Ssklower 		return (pk_control (so, (int)m, (caddr_t)nam,
5941936Ssklower 			(struct ifnet *)control));
6045895Ssklower 	if (control && control -> m_len) {
6141936Ssklower 		error = EINVAL;
6241936Ssklower 		goto release;
6341595Ssklower 	}
6441936Ssklower 	if (lcp == NULL && req != PRU_ATTACH) {
6541936Ssklower 		error = EINVAL;
6641936Ssklower 		goto release;
6741595Ssklower 	}
6841595Ssklower 
6941595Ssklower /*
7041595Ssklower 	pk_trace (pkcbhead, TR_USER, (struct pklcd *)0,
7141595Ssklower 		req, (struct x25_packet *)0);
7241595Ssklower */
7341595Ssklower 
7441595Ssklower 	switch (req) {
7541595Ssklower 	/*
7641595Ssklower 	 *  X.25 attaches to socket via PRU_ATTACH and allocates a logical
7741595Ssklower 	 *  channel descriptor.  If the socket is to  receive connections,
7841595Ssklower 	 *  then the LISTEN state is entered.
7941595Ssklower 	 */
8041595Ssklower 	case PRU_ATTACH:
8141595Ssklower 		if (lcp) {
8241595Ssklower 			error = EISCONN;
8341595Ssklower 			/* Socket already connected. */
8441595Ssklower 			break;
8541595Ssklower 		}
8645165Ssklower 		lcp = pk_attach (so);
8745165Ssklower 		if (lcp == 0)
8845165Ssklower 			error = ENOBUFS;
8941595Ssklower 		break;
9041595Ssklower 
9141595Ssklower 	/*
9241595Ssklower 	 *  Detach a logical channel from the socket. If the state of the
9341595Ssklower 	 *  channel is embryonic, simply discard it. Otherwise we have to
9441595Ssklower 	 *  initiate a PRU_DISCONNECT which will finish later.
9541595Ssklower 	 */
9641595Ssklower 	case PRU_DETACH:
9741595Ssklower 		pk_disconnect (lcp);
9841595Ssklower 		break;
9941595Ssklower 
10041595Ssklower 	/*
10141595Ssklower 	 *  Give the socket an address.
10241595Ssklower 	 */
10341595Ssklower 	case PRU_BIND:
10441595Ssklower 		if (nam -> m_len == sizeof (struct x25_sockaddr))
10541595Ssklower 			old_to_new (nam);
10641595Ssklower 		error = pk_bind (lcp, nam);
10741595Ssklower 		break;
10841595Ssklower 
10941595Ssklower 	/*
11041595Ssklower 	 *  Prepare to accept connections.
11141595Ssklower 	 */
11241595Ssklower 	case PRU_LISTEN:
11345895Ssklower 		error = pk_listen (lcp);
11441595Ssklower 		break;
11541595Ssklower 
11641595Ssklower 	/*
11741595Ssklower 	 *  Initiate a CALL REQUEST to peer entity. Enter state SENT_CALL
11841595Ssklower 	 *  and mark the socket as connecting. Set timer waiting for
11941595Ssklower 	 *  CALL ACCEPT or CLEAR.
12041595Ssklower 	 */
12141595Ssklower 	case PRU_CONNECT:
12241595Ssklower 		if (nam -> m_len == sizeof (struct x25_sockaddr))
12341595Ssklower 			old_to_new (nam);
12445895Ssklower 		if (pk_checksockaddr (nam))
12545895Ssklower 			return (EINVAL);
12645895Ssklower 		error = pk_connect (lcp, mtod (nam, struct sockaddr_x25 *));
12741595Ssklower 		break;
12841595Ssklower 
12941595Ssklower 	/*
13041595Ssklower 	 *  Initiate a disconnect to peer entity via a CLEAR REQUEST packet.
13141595Ssklower 	 *  The socket will be disconnected when we receive a confirmation
13241595Ssklower 	 *  or a clear collision.
13341595Ssklower 	 */
13441595Ssklower 	case PRU_DISCONNECT:
13541595Ssklower 		pk_disconnect (lcp);
13641595Ssklower 		break;
13741595Ssklower 
13841595Ssklower 	/*
13941595Ssklower 	 *  Accept an INCOMING CALL. Most of the work has already been done
14041595Ssklower 	 *  by pk_input. Just return the callers address to the user.
14141595Ssklower 	 */
14241595Ssklower 	case PRU_ACCEPT:
14341595Ssklower 		if (lcp -> lcd_craddr == NULL)
14441595Ssklower 			break;
14541595Ssklower 		bcopy ((caddr_t)lcp -> lcd_craddr, mtod (nam, caddr_t),
14641595Ssklower 			sizeof (struct sockaddr_x25));
14741595Ssklower 		nam -> m_len = sizeof (struct sockaddr_x25);
14841595Ssklower 		if (lcp -> lcd_flags & X25_OLDSOCKADDR)
14941595Ssklower 			new_to_old (nam);
15041595Ssklower 		break;
15141595Ssklower 
15241595Ssklower 	/*
15341595Ssklower 	 *  After a receive, we should send a RR.
15441595Ssklower 	 */
15541595Ssklower 	case PRU_RCVD:
15649933Ssklower 		pk_flowcontrol (lcp, /*sbspace (&so -> so_rcv) <= */ 0, 1);
15741595Ssklower 		break;
15841595Ssklower 
15941595Ssklower 	/*
16045895Ssklower 	 *  Send INTERRUPT packet.
16145895Ssklower 	 */
16245895Ssklower 	case PRU_SENDOOB:
16345895Ssklower 		if (m == 0) {
16445895Ssklower 			MGETHDR(m, M_WAITOK, MT_OOBDATA);
16545895Ssklower 			m -> m_pkthdr.len = m -> m_len = 1;
16647261Ssklower 			*mtod (m, octet *) = 0;
16745895Ssklower 		}
16845895Ssklower 		if (m -> m_pkthdr.len > 32) {
16947261Ssklower 			m_freem (m);
17045895Ssklower 			error = EMSGSIZE;
17145895Ssklower 			break;
17245895Ssklower 		}
17345895Ssklower 		MCHTYPE(m, MT_OOBDATA);
17445895Ssklower 		/* FALLTHROUGH */
17545895Ssklower 
17645895Ssklower 	/*
17741595Ssklower 	 *  Do send by placing data on the socket output queue.
17841595Ssklower 	 */
17941595Ssklower 	case PRU_SEND:
18045895Ssklower 		if (control) {
18147261Ssklower 			register struct cmsghdr *ch = mtod (m, struct cmsghdr *);
18245895Ssklower 			control -> m_len -= sizeof (*ch);
18345895Ssklower 			control -> m_data += sizeof (*ch);
18449933Ssklower 			error = pk_ctloutput (PRCO_SETOPT, so, ch -> cmsg_level,
18545895Ssklower 					ch -> cmsg_type, &control);
18645895Ssklower 		}
18749933Ssklower 		if (error == 0 && m)
18845895Ssklower 			error = pk_send (lcp, m);
18941595Ssklower 		break;
19041595Ssklower 
19141595Ssklower 	/*
19241595Ssklower 	 *  Abort a virtual circuit. For example all completed calls
19341595Ssklower 	 *  waiting acceptance.
19441595Ssklower 	 */
19541595Ssklower 	case PRU_ABORT:
19641595Ssklower 		pk_disconnect (lcp);
19741595Ssklower 		break;
19841595Ssklower 
19941595Ssklower 	/* Begin unimplemented hooks. */
20041595Ssklower 
20141595Ssklower 	case PRU_SHUTDOWN:
20241595Ssklower 		error = EOPNOTSUPP;
20341595Ssklower 		break;
20441595Ssklower 
20541595Ssklower 	case PRU_CONTROL:
20641595Ssklower 		error = EOPNOTSUPP;
20741595Ssklower 		break;
20841595Ssklower 
20941595Ssklower 	case PRU_SENSE:
21041595Ssklower #ifdef BSD4_3
21141595Ssklower 		((struct stat *)m) -> st_blksize = so -> so_snd.sb_hiwat;
21241595Ssklower #else
21341595Ssklower 		error = EOPNOTSUPP;
21441595Ssklower #endif
21541595Ssklower 		break;
21641595Ssklower 
21741595Ssklower 	/* End unimplemented hooks. */
21841595Ssklower 
21941595Ssklower 	case PRU_SOCKADDR:
22041595Ssklower 		if (lcp -> lcd_ceaddr == 0)
22141595Ssklower 			return (EADDRNOTAVAIL);
22241595Ssklower 		nam -> m_len = sizeof (struct sockaddr_x25);
22341595Ssklower 		bcopy ((caddr_t)lcp -> lcd_ceaddr, mtod (nam, caddr_t),
22441595Ssklower 			sizeof (struct sockaddr_x25));
22541595Ssklower 		if (lcp -> lcd_flags & X25_OLDSOCKADDR)
22641595Ssklower 			new_to_old (nam);
22741595Ssklower 		break;
22841595Ssklower 
22941595Ssklower 	case PRU_PEERADDR:
23041595Ssklower 		if (lcp -> lcd_state != DATA_TRANSFER)
23141595Ssklower 			return (ENOTCONN);
23241595Ssklower 		nam -> m_len = sizeof (struct sockaddr_x25);
23341595Ssklower 		bcopy (lcp -> lcd_craddr ? (caddr_t)lcp -> lcd_craddr :
23441595Ssklower 			(caddr_t)lcp -> lcd_ceaddr,
23541595Ssklower 			mtod (nam, caddr_t), sizeof (struct sockaddr_x25));
23641595Ssklower 		if (lcp -> lcd_flags & X25_OLDSOCKADDR)
23741595Ssklower 			new_to_old (nam);
23841595Ssklower 		break;
23941595Ssklower 
24041595Ssklower 	/*
24141595Ssklower 	 *  Receive INTERRUPT packet.
24241595Ssklower 	 */
24341595Ssklower 	case PRU_RCVOOB:
24445895Ssklower 		if (so -> so_options & SO_OOBINLINE) {
24545895Ssklower 			register struct mbuf *n  = so -> so_rcv.sb_mb;
24645895Ssklower 			if (n && n -> m_type == MT_OOBDATA) {
24745895Ssklower 				unsigned len =  n -> m_pkthdr.len;
24845895Ssklower 				so -> so_rcv.sb_mb = n -> m_nextpkt;
24945895Ssklower 				if (len !=  n -> m_len &&
25047261Ssklower 				    (n = m_pullup (n, len)) == 0)
25145895Ssklower 					break;
25245895Ssklower 				m -> m_len = len;
25347261Ssklower 				bcopy (mtod (m, caddr_t), mtod (n, caddr_t), len);
25447261Ssklower 				m_freem (n);
25545895Ssklower 			}
25645895Ssklower 			break;
25745895Ssklower 		}
25841595Ssklower 		m -> m_len = 1;
25941595Ssklower 		*mtod (m, char *) = lcp -> lcd_intrdata;
26041595Ssklower 		break;
26141595Ssklower 
26241595Ssklower 	default:
26341595Ssklower 		panic ("pk_usrreq");
26441595Ssklower 	}
26541936Ssklower release:
26641936Ssklower 	if (control != NULL)
26747261Ssklower 		m_freem (control);
26841595Ssklower 	return (error);
26941595Ssklower }
27041595Ssklower 
27142277Ssklower /*
27242277Ssklower  * If you want to use UBC X.25 level 3 in conjunction with some
27345895Ssklower  * other X.25 level 2 driver, have the ifp -> if_ioctl routine
27449933Ssklower  * assign pk_start to ia -> ia_start when called with SIOCSIFCONF_X25.
27542277Ssklower  */
27642277Ssklower /* ARGSUSED */
27742277Ssklower pk_start (lcp)
27842277Ssklower register struct pklcd *lcp;
27942277Ssklower {
28049027Ssklower 	pk_output (lcp);
28149027Ssklower 	return (0); /* XXX pk_output should return a value */
28242277Ssklower }
28342277Ssklower 
28449933Ssklower #ifndef _offsetof
28549933Ssklower #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
28649933Ssklower #endif
28749933Ssklower struct sockaddr_x25 pk_sockmask = {
288*57024Ssklower 	_offsetof(struct sockaddr_x25, x25_addr[0]),      /* x25_len */
289*57024Ssklower 	0,                                                /* x25_family */
290*57024Ssklower 	-1,                                               /* x25_net id */
291*57024Ssklower };
29249933Ssklower 
29341595Ssklower /*ARGSUSED*/
29441595Ssklower pk_control (so, cmd, data, ifp)
29541595Ssklower struct socket *so;
29641595Ssklower int cmd;
29741595Ssklower caddr_t data;
29841595Ssklower register struct ifnet *ifp;
29941595Ssklower {
30042140Ssklower 	register struct ifreq_x25 *ifr = (struct ifreq_x25 *)data;
30141595Ssklower 	register struct ifaddr *ifa = 0;
30241936Ssklower 	register struct x25_ifaddr *ia = 0;
30342277Ssklower 	struct pklcd *dev_lcp = 0;
30445297Ssklower 	int error, s, old_maxlcn;
30541936Ssklower 	unsigned n;
30641595Ssklower 
30741595Ssklower 	/*
30841595Ssklower 	 * Find address for this interface, if it exists.
30941595Ssklower 	 */
31041595Ssklower 	if (ifp)
31145895Ssklower 		for (ifa = ifp -> if_addrlist; ifa; ifa = ifa -> ifa_next)
31245895Ssklower 			if (ifa -> ifa_addr -> sa_family == AF_CCITT)
31341595Ssklower 				break;
31441595Ssklower 
31541936Ssklower 	ia = (struct x25_ifaddr *)ifa;
31641595Ssklower 	switch (cmd) {
31742140Ssklower 	case SIOCGIFCONF_X25:
31841595Ssklower 		if (ifa == 0)
31941595Ssklower 			return (EADDRNOTAVAIL);
32045895Ssklower 		ifr -> ifr_xc = ia -> ia_xc;
32141595Ssklower 		return (0);
32241595Ssklower 
32342140Ssklower 	case SIOCSIFCONF_X25:
32450241Ssklower 		if ((so->so_state & SS_PRIV) == 0)
32550241Ssklower 			return (EPERM);
32641595Ssklower 		if (ifp == 0)
32747261Ssklower 			panic ("pk_control");
32841595Ssklower 		if (ifa == (struct ifaddr *)0) {
32941595Ssklower 			register struct mbuf *m;
33041595Ssklower 
33142277Ssklower 			MALLOC(ia, struct x25_ifaddr *, sizeof (*ia),
33242277Ssklower 				M_IFADDR, M_WAITOK);
33342277Ssklower 			if (ia == 0)
33441595Ssklower 				return (ENOBUFS);
33547261Ssklower 			bzero ((caddr_t)ia, sizeof (*ia));
33645895Ssklower 			if (ifa = ifp -> if_addrlist) {
33745895Ssklower 				for ( ; ifa -> ifa_next; ifa = ifa -> ifa_next)
33841595Ssklower 					;
33945895Ssklower 				ifa -> ifa_next = &ia -> ia_ifa;
34041595Ssklower 			} else
34145895Ssklower 				ifp -> if_addrlist = &ia -> ia_ifa;
34245895Ssklower 			ifa = &ia -> ia_ifa;
34349933Ssklower 			ifa -> ifa_netmask = (struct sockaddr *)&pk_sockmask;
34445895Ssklower 			ifa -> ifa_addr = (struct sockaddr *)&ia -> ia_xc.xc_addr;
34549933Ssklower 			ifa -> ifa_dstaddr = (struct sockaddr *)&ia -> ia_dstaddr; /* XXX */
34645895Ssklower 			ia -> ia_ifp = ifp;
34749933Ssklower 			ia -> ia_dstaddr.x25_family = AF_CCITT;
34849933Ssklower 			ia -> ia_dstaddr.x25_len = pk_sockmask.x25_len;
349*57024Ssklower 		} else if (ISISO8802(ifp) == 0) {
35049933Ssklower 			rtinit (ifa, (int)RTM_DELETE, 0);
35141595Ssklower 		}
35245895Ssklower 		old_maxlcn = ia -> ia_maxlcn;
35345895Ssklower 		ia -> ia_xc = ifr -> ifr_xc;
35449933Ssklower 		ia -> ia_dstaddr.x25_net = ia -> ia_xc.xc_addr.x25_net;
35549933Ssklower 		if (ia -> ia_maxlcn != old_maxlcn && old_maxlcn != 0) {
35649933Ssklower 			/* VERY messy XXX */
35749933Ssklower 			register struct pkcb *pkp;
358*57024Ssklower 			FOR_ALL_PKCBS(pkp)
35949933Ssklower 				if (pkp -> pk_ia == ia)
36049933Ssklower 					pk_resize (pkp);
36141936Ssklower 		}
36241595Ssklower 		/*
36341595Ssklower 		 * Give the interface a chance to initialize if this
364*57024Ssklower p		 * is its first address, and to validate the address.
36541595Ssklower 		 */
36649933Ssklower 		ia -> ia_start = pk_start;
36741936Ssklower 		s = splimp();
36845895Ssklower 		if (ifp -> if_ioctl)
369*57024Ssklower 			error = (*ifp -> if_ioctl)(ifp, SIOCSIFCONF_X25,
370*57024Ssklower 						   (caddr_t) ifa);
37145297Ssklower 		if (error)
37245895Ssklower 			ifp -> if_flags &= ~IFF_UP;
373*57024Ssklower 		else if (ISISO8802(ifp) == 0)
37449933Ssklower 			error = rtinit (ifa, (int)RTM_ADD, RTF_UP);
37545895Ssklower 		splx (s);
37641936Ssklower 		return (error);
37741595Ssklower 
37841595Ssklower 	default:
37945895Ssklower 		if (ifp == 0 || ifp -> if_ioctl == 0)
38041595Ssklower 			return (EOPNOTSUPP);
38145895Ssklower 		return ((*ifp -> if_ioctl)(ifp, cmd, data));
38241595Ssklower 	}
38341595Ssklower }
38441595Ssklower 
38547261Ssklower pk_ctloutput (cmd, so, level, optname, mp)
38645165Ssklower struct socket *so;
38745165Ssklower struct mbuf **mp;
38845165Ssklower int cmd, level, optname;
38945165Ssklower {
39045165Ssklower 	register struct mbuf *m = *mp;
39145895Ssklower 	register struct pklcd *lcp = (struct pklcd *) so -> so_pcb;
39249933Ssklower 	int error = EOPNOTSUPP;
39345165Ssklower 
39449933Ssklower 	if (m == 0)
39549933Ssklower 		return (EINVAL);
39645165Ssklower 	if (cmd == PRCO_SETOPT) switch (optname) {
39749933Ssklower 	case PK_FACILITIES:
39845165Ssklower 		if (m == 0)
39945165Ssklower 			return (EINVAL);
40049933Ssklower 		lcp -> lcd_facilities = m;
40149933Ssklower 		*mp = 0;
40249933Ssklower 		return (0);
40349933Ssklower 
40449933Ssklower 	case PK_ACCTFILE:
40550241Ssklower 		if ((so->so_state & SS_PRIV) == 0)
40650241Ssklower 			error = EPERM;
40750241Ssklower 		else if (m -> m_len)
40847261Ssklower 			error = pk_accton (mtod (m, char *));
40945165Ssklower 		else
41045895Ssklower 			error = pk_accton ((char *)0);
41149933Ssklower 		break;
41245895Ssklower 
41349933Ssklower 	case PK_RTATTACH:
41449933Ssklower 		error = pk_rtattach (so, m);
41549933Ssklower 		break;
41649933Ssklower 
41749933Ssklower 	case PK_PRLISTEN:
41849933Ssklower 		error = pk_user_protolisten (mtod (m, u_char *));
41945165Ssklower 	}
42045165Ssklower 	if (*mp) {
42145895Ssklower 		(void) m_freem (*mp);
42245165Ssklower 		*mp = 0;
42345165Ssklower 	}
42450156Ssklower 	return (error);
42545165Ssklower 
42645165Ssklower }
42745165Ssklower 
42849933Ssklower 
42941595Ssklower /*
43041595Ssklower  * Do an in-place conversion of an "old style"
43141595Ssklower  * socket address to the new style
43241595Ssklower  */
43341595Ssklower 
43441595Ssklower static
43541595Ssklower old_to_new (m)
43641595Ssklower register struct mbuf *m;
43741595Ssklower {
43841595Ssklower 	register struct x25_sockaddr *oldp;
43941595Ssklower 	register struct sockaddr_x25 *newp;
44041595Ssklower 	register char *ocp, *ncp;
44141595Ssklower 	struct sockaddr_x25 new;
44241595Ssklower 
44341595Ssklower 	oldp = mtod (m, struct x25_sockaddr *);
44441595Ssklower 	newp = &new;
44541595Ssklower 	bzero ((caddr_t)newp, sizeof (*newp));
44641595Ssklower 
44741595Ssklower 	newp -> x25_family = AF_CCITT;
44848753Ssklower 	newp -> x25_len = sizeof(*newp);
44945895Ssklower 	newp -> x25_opts.op_flags = (oldp -> xaddr_facilities & X25_REVERSE_CHARGE)
45041595Ssklower 		| X25_MQBIT | X25_OLDSOCKADDR;
45141595Ssklower 	if (oldp -> xaddr_facilities & XS_HIPRIO)	/* Datapac specific */
45241595Ssklower 		newp -> x25_opts.op_psize = X25_PS128;
45341595Ssklower 	bcopy ((caddr_t)oldp -> xaddr_addr, newp -> x25_addr,
45448753Ssklower 	       (unsigned)min (oldp -> xaddr_len, sizeof (newp -> x25_addr) - 1));
45548753Ssklower 	if (bcmp ((caddr_t)oldp -> xaddr_proto, newp -> x25_udata, 4) != 0) {
45648753Ssklower 		bcopy ((caddr_t)oldp -> xaddr_proto, newp -> x25_udata, 4);
45748753Ssklower 		newp -> x25_udlen = 4;
45848753Ssklower 	}
45941595Ssklower 	ocp = (caddr_t)oldp -> xaddr_userdata;
46041595Ssklower 	ncp = newp -> x25_udata + 4;
46141595Ssklower 	while (*ocp && ocp < (caddr_t)oldp -> xaddr_userdata + 12) {
46248753Ssklower 		if (newp -> x25_udlen == 0)
46348753Ssklower 			newp -> x25_udlen = 4;
46441595Ssklower 		*ncp++ = *ocp++;
46541595Ssklower 		newp -> x25_udlen++;
46641595Ssklower 	}
46741595Ssklower 	bcopy ((caddr_t)newp, mtod (m, char *), sizeof (*newp));
46845895Ssklower 	m -> m_len = sizeof (*newp);
46941595Ssklower }
47041595Ssklower 
47141595Ssklower /*
47241595Ssklower  * Do an in-place conversion of a new style
47341595Ssklower  * socket address to the old style
47441595Ssklower  */
47541595Ssklower 
47641595Ssklower static
47741595Ssklower new_to_old (m)
47841595Ssklower register struct mbuf *m;
47941595Ssklower {
48041595Ssklower 	register struct x25_sockaddr *oldp;
48141595Ssklower 	register struct sockaddr_x25 *newp;
48241595Ssklower 	register char *ocp, *ncp;
48341595Ssklower 	struct x25_sockaddr old;
48441595Ssklower 
48541595Ssklower 	oldp = &old;
48641595Ssklower 	newp = mtod (m, struct sockaddr_x25 *);
48741595Ssklower 	bzero ((caddr_t)oldp, sizeof (*oldp));
48841595Ssklower 
48941595Ssklower 	oldp -> xaddr_facilities = newp -> x25_opts.op_flags & X25_REVERSE_CHARGE;
49041595Ssklower 	if (newp -> x25_opts.op_psize == X25_PS128)
49141595Ssklower 		oldp -> xaddr_facilities |= XS_HIPRIO;	/* Datapac specific */
49241595Ssklower 	ocp = (char *)oldp -> xaddr_addr;
49341595Ssklower 	ncp = newp -> x25_addr;
49441595Ssklower 	while (*ncp) {
49541595Ssklower 		*ocp++ = *ncp++;
49641595Ssklower 		oldp -> xaddr_len++;
49741595Ssklower 	}
49841595Ssklower 
49941595Ssklower 	bcopy (newp -> x25_udata, (caddr_t)oldp -> xaddr_proto, 4);
50048753Ssklower 	if (newp -> x25_udlen > 4)
50148753Ssklower 		bcopy (newp -> x25_udata + 4, (caddr_t)oldp -> xaddr_userdata,
50248753Ssklower 			(unsigned)(newp -> x25_udlen - 4));
50341595Ssklower 
50441595Ssklower 	bcopy ((caddr_t)oldp, mtod (m, char *), sizeof (*oldp));
50541595Ssklower 	m -> m_len = sizeof (*oldp);
50641595Ssklower }
50741595Ssklower 
50845895Ssklower 
50945895Ssklower pk_checksockaddr (m)
51045895Ssklower struct mbuf *m;
51145895Ssklower {
51245895Ssklower 	register struct sockaddr_x25 *sa = mtod (m, struct sockaddr_x25 *);
51345895Ssklower 	register char *cp;
51445895Ssklower 
51545895Ssklower 	if (m -> m_len != sizeof (struct sockaddr_x25))
51645895Ssklower 		return (1);
51745895Ssklower 	if (sa -> x25_family != AF_CCITT ||
51845895Ssklower 		sa -> x25_udlen > sizeof (sa -> x25_udata))
51945895Ssklower 		return (1);
52045895Ssklower 	for (cp = sa -> x25_addr; *cp; cp++) {
52145895Ssklower 		if (*cp < '0' || *cp > '9' ||
52245895Ssklower 			cp >= &sa -> x25_addr[sizeof (sa -> x25_addr) - 1])
52345895Ssklower 			return (1);
52445895Ssklower 	}
52545895Ssklower 	return (0);
52645895Ssklower }
52749027Ssklower 
52841595Ssklower pk_send (lcp, m)
52945297Ssklower struct pklcd *lcp;
53041595Ssklower register struct mbuf *m;
53141595Ssklower {
53245895Ssklower 	int mqbit = 0, error = 0;
53345895Ssklower 	register struct x25_packet *xp;
53449027Ssklower 	register struct socket *so;
53541595Ssklower 
53645895Ssklower 	if (m -> m_type == MT_OOBDATA) {
53745895Ssklower 		if (lcp -> lcd_intrconf_pending)
53845895Ssklower 			error = ETOOMANYREFS;
53945895Ssklower 		if (m -> m_pkthdr.len > 32)
54045895Ssklower 			error = EMSGSIZE;
54145895Ssklower 		M_PREPEND(m, PKHEADERLN, M_WAITOK);
54245895Ssklower 		if (m == 0 || error)
54345895Ssklower 			goto bad;
54445895Ssklower 		*(mtod (m, octet *)) = 0;
54545895Ssklower 		xp = mtod (m, struct x25_packet *);
546*57024Ssklower 		X25SBITS(xp -> bits, fmt_identifier, 1);
54745895Ssklower 		xp -> packet_type = X25_INTERRUPT;
54845895Ssklower 		SET_LCN(xp, lcp -> lcd_lcn);
54949027Ssklower 		sbinsertoob ( (so = lcp -> lcd_so) ?
55049027Ssklower 			&so -> so_snd : &lcp -> lcd_sb, m);
55149027Ssklower 		goto send;
55245895Ssklower 	}
55341595Ssklower 	/*
55441595Ssklower 	 * Application has elected (at call setup time) to prepend
55541595Ssklower 	 * a control byte to each packet written indicating m-bit
55641595Ssklower 	 * and q-bit status.  Examine and then discard this byte.
55741595Ssklower 	 */
55841595Ssklower 	if (lcp -> lcd_flags & X25_MQBIT) {
55941595Ssklower 		if (m -> m_len < 1) {
56045297Ssklower 			m_freem (m);
56141595Ssklower 			return (EMSGSIZE);
56241595Ssklower 		}
56345895Ssklower 		mqbit = *(mtod (m, u_char *));
56441595Ssklower 		m -> m_len--;
56541936Ssklower 		m -> m_data++;
56645297Ssklower 		m -> m_pkthdr.len--;
56741595Ssklower 	}
56849027Ssklower 	error = pk_fragment (lcp, m, mqbit & 0x80, mqbit & 0x40, 1);
56949027Ssklower send:
57049027Ssklower 	if (error == 0 && lcp -> lcd_state == DATA_TRANSFER)
57149027Ssklower 		lcp -> lcd_send (lcp); /* XXXXXXXXX fix pk_output!!! */
57245297Ssklower 	return (error);
57345895Ssklower bad:
57445895Ssklower 	if (m)
57545895Ssklower 		m_freem (m);
57645895Ssklower 	return (error);
57741595Ssklower }
578