xref: /csrg-svn/sys/netccitt/pk_usrreq.c (revision 68166)
141709Ssklower /*
241709Ssklower  * Copyright (c) University of British Columbia, 1984
357024Ssklower  * Copyright (C) Computer Science Department IV,
457024Ssklower  * 		 University of Erlangen-Nuremberg, Germany, 1992
563216Sbostic  * Copyright (c) 1991, 1992, 1993
663216Sbostic  *	The Regents of the University of California.  All rights reserved.
741709Ssklower  *
857024Ssklower  * This code is derived from software contributed to Berkeley by the
957024Ssklower  * Laboratory for Computation Vision and the Computer Science Department
1057024Ssklower  * of the the University of British Columbia and the Computer Science
1157024Ssklower  * Department (IV) of the University of Erlangen-Nuremberg, Germany.
1241709Ssklower  *
1341709Ssklower  * %sccs.include.redist.c%
1441709Ssklower  *
15*68166Scgd  *	@(#)pk_usrreq.c	8.2 (Berkeley) 01/09/95
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>
2957032Ssklower #include <net/if_types.h>
3056530Sbostic #include <net/route.h>
3141595Ssklower 
3256530Sbostic #include <netccitt/x25.h>
3356530Sbostic #include <netccitt/pk.h>
3456530Sbostic #include <netccitt/pk_var.h>
3542140Ssklower 
3657024Ssklower static old_to_new();
3757024Ssklower static new_to_old();
3841595Ssklower /*
3941595Ssklower  *
4041595Ssklower  *  X.25 Packet level protocol interface to socket abstraction.
4141595Ssklower  *
4241595Ssklower  *  Process an X.25 user request on a logical channel.  If this is a send
4341595Ssklower  *  request then m is the mbuf chain of the send data. If this is a timer
4441595Ssklower  *  expiration (called from the software clock routine) them timertype is
4541595Ssklower  *  the particular timer.
4641595Ssklower  *
4741595Ssklower  */
4841595Ssklower 
4941936Ssklower pk_usrreq (so, req, m, nam, control)
5041595Ssklower struct socket *so;
5141595Ssklower int req;
5241595Ssklower register struct mbuf *m, *nam;
5341936Ssklower struct mbuf *control;
5441595Ssklower {
5541595Ssklower 	register struct pklcd *lcp = (struct pklcd *) so -> so_pcb;
5641936Ssklower 	register int error = 0;
5741595Ssklower 
5841936Ssklower 	if (req == PRU_CONTROL)
5947261Ssklower 		return (pk_control (so, (int)m, (caddr_t)nam,
6041936Ssklower 			(struct ifnet *)control));
6145895Ssklower 	if (control && control -> m_len) {
6241936Ssklower 		error = EINVAL;
6341936Ssklower 		goto release;
6441595Ssklower 	}
6541936Ssklower 	if (lcp == NULL && req != PRU_ATTACH) {
6641936Ssklower 		error = EINVAL;
6741936Ssklower 		goto release;
6841595Ssklower 	}
6941595Ssklower 
7041595Ssklower /*
7141595Ssklower 	pk_trace (pkcbhead, TR_USER, (struct pklcd *)0,
7241595Ssklower 		req, (struct x25_packet *)0);
7341595Ssklower */
7441595Ssklower 
7541595Ssklower 	switch (req) {
7641595Ssklower 	/*
7741595Ssklower 	 *  X.25 attaches to socket via PRU_ATTACH and allocates a logical
7841595Ssklower 	 *  channel descriptor.  If the socket is to  receive connections,
7941595Ssklower 	 *  then the LISTEN state is entered.
8041595Ssklower 	 */
8141595Ssklower 	case PRU_ATTACH:
8241595Ssklower 		if (lcp) {
8341595Ssklower 			error = EISCONN;
8441595Ssklower 			/* Socket already connected. */
8541595Ssklower 			break;
8641595Ssklower 		}
8745165Ssklower 		lcp = pk_attach (so);
8845165Ssklower 		if (lcp == 0)
8945165Ssklower 			error = ENOBUFS;
9041595Ssklower 		break;
9141595Ssklower 
9241595Ssklower 	/*
9341595Ssklower 	 *  Detach a logical channel from the socket. If the state of the
9441595Ssklower 	 *  channel is embryonic, simply discard it. Otherwise we have to
9541595Ssklower 	 *  initiate a PRU_DISCONNECT which will finish later.
9641595Ssklower 	 */
9741595Ssklower 	case PRU_DETACH:
9841595Ssklower 		pk_disconnect (lcp);
9941595Ssklower 		break;
10041595Ssklower 
10141595Ssklower 	/*
10241595Ssklower 	 *  Give the socket an address.
10341595Ssklower 	 */
10441595Ssklower 	case PRU_BIND:
10541595Ssklower 		if (nam -> m_len == sizeof (struct x25_sockaddr))
10641595Ssklower 			old_to_new (nam);
10741595Ssklower 		error = pk_bind (lcp, nam);
10841595Ssklower 		break;
10941595Ssklower 
11041595Ssklower 	/*
11141595Ssklower 	 *  Prepare to accept connections.
11241595Ssklower 	 */
11341595Ssklower 	case PRU_LISTEN:
11445895Ssklower 		error = pk_listen (lcp);
11541595Ssklower 		break;
11641595Ssklower 
11741595Ssklower 	/*
11841595Ssklower 	 *  Initiate a CALL REQUEST to peer entity. Enter state SENT_CALL
11941595Ssklower 	 *  and mark the socket as connecting. Set timer waiting for
12041595Ssklower 	 *  CALL ACCEPT or CLEAR.
12141595Ssklower 	 */
12241595Ssklower 	case PRU_CONNECT:
12341595Ssklower 		if (nam -> m_len == sizeof (struct x25_sockaddr))
12441595Ssklower 			old_to_new (nam);
12545895Ssklower 		if (pk_checksockaddr (nam))
12645895Ssklower 			return (EINVAL);
12745895Ssklower 		error = pk_connect (lcp, mtod (nam, struct sockaddr_x25 *));
12841595Ssklower 		break;
12941595Ssklower 
13041595Ssklower 	/*
13141595Ssklower 	 *  Initiate a disconnect to peer entity via a CLEAR REQUEST packet.
13241595Ssklower 	 *  The socket will be disconnected when we receive a confirmation
13341595Ssklower 	 *  or a clear collision.
13441595Ssklower 	 */
13541595Ssklower 	case PRU_DISCONNECT:
13641595Ssklower 		pk_disconnect (lcp);
13741595Ssklower 		break;
13841595Ssklower 
13941595Ssklower 	/*
14041595Ssklower 	 *  Accept an INCOMING CALL. Most of the work has already been done
14141595Ssklower 	 *  by pk_input. Just return the callers address to the user.
14241595Ssklower 	 */
14341595Ssklower 	case PRU_ACCEPT:
14441595Ssklower 		if (lcp -> lcd_craddr == NULL)
14541595Ssklower 			break;
14641595Ssklower 		bcopy ((caddr_t)lcp -> lcd_craddr, mtod (nam, caddr_t),
14741595Ssklower 			sizeof (struct sockaddr_x25));
14841595Ssklower 		nam -> m_len = sizeof (struct sockaddr_x25);
14941595Ssklower 		if (lcp -> lcd_flags & X25_OLDSOCKADDR)
15041595Ssklower 			new_to_old (nam);
15141595Ssklower 		break;
15241595Ssklower 
15341595Ssklower 	/*
15441595Ssklower 	 *  After a receive, we should send a RR.
15541595Ssklower 	 */
15641595Ssklower 	case PRU_RCVD:
15749933Ssklower 		pk_flowcontrol (lcp, /*sbspace (&so -> so_rcv) <= */ 0, 1);
15841595Ssklower 		break;
15941595Ssklower 
16041595Ssklower 	/*
16145895Ssklower 	 *  Send INTERRUPT packet.
16245895Ssklower 	 */
16345895Ssklower 	case PRU_SENDOOB:
16445895Ssklower 		if (m == 0) {
16545895Ssklower 			MGETHDR(m, M_WAITOK, MT_OOBDATA);
16645895Ssklower 			m -> m_pkthdr.len = m -> m_len = 1;
16747261Ssklower 			*mtod (m, octet *) = 0;
16845895Ssklower 		}
16945895Ssklower 		if (m -> m_pkthdr.len > 32) {
17047261Ssklower 			m_freem (m);
17145895Ssklower 			error = EMSGSIZE;
17245895Ssklower 			break;
17345895Ssklower 		}
17445895Ssklower 		MCHTYPE(m, MT_OOBDATA);
17545895Ssklower 		/* FALLTHROUGH */
17645895Ssklower 
17745895Ssklower 	/*
17841595Ssklower 	 *  Do send by placing data on the socket output queue.
17941595Ssklower 	 */
18041595Ssklower 	case PRU_SEND:
18145895Ssklower 		if (control) {
18247261Ssklower 			register struct cmsghdr *ch = mtod (m, struct cmsghdr *);
18345895Ssklower 			control -> m_len -= sizeof (*ch);
18445895Ssklower 			control -> m_data += sizeof (*ch);
18549933Ssklower 			error = pk_ctloutput (PRCO_SETOPT, so, ch -> cmsg_level,
18645895Ssklower 					ch -> cmsg_type, &control);
18745895Ssklower 		}
18849933Ssklower 		if (error == 0 && m)
18945895Ssklower 			error = pk_send (lcp, m);
19041595Ssklower 		break;
19141595Ssklower 
19241595Ssklower 	/*
19341595Ssklower 	 *  Abort a virtual circuit. For example all completed calls
19441595Ssklower 	 *  waiting acceptance.
19541595Ssklower 	 */
19641595Ssklower 	case PRU_ABORT:
19741595Ssklower 		pk_disconnect (lcp);
19841595Ssklower 		break;
19941595Ssklower 
20041595Ssklower 	/* Begin unimplemented hooks. */
20141595Ssklower 
20241595Ssklower 	case PRU_SHUTDOWN:
20341595Ssklower 		error = EOPNOTSUPP;
20441595Ssklower 		break;
20541595Ssklower 
20641595Ssklower 	case PRU_CONTROL:
20741595Ssklower 		error = EOPNOTSUPP;
20841595Ssklower 		break;
20941595Ssklower 
21041595Ssklower 	case PRU_SENSE:
21141595Ssklower #ifdef BSD4_3
21241595Ssklower 		((struct stat *)m) -> st_blksize = so -> so_snd.sb_hiwat;
21341595Ssklower #else
21441595Ssklower 		error = EOPNOTSUPP;
21541595Ssklower #endif
21641595Ssklower 		break;
21741595Ssklower 
21841595Ssklower 	/* End unimplemented hooks. */
21941595Ssklower 
22041595Ssklower 	case PRU_SOCKADDR:
22141595Ssklower 		if (lcp -> lcd_ceaddr == 0)
22241595Ssklower 			return (EADDRNOTAVAIL);
22341595Ssklower 		nam -> m_len = sizeof (struct sockaddr_x25);
22441595Ssklower 		bcopy ((caddr_t)lcp -> lcd_ceaddr, mtod (nam, caddr_t),
22541595Ssklower 			sizeof (struct sockaddr_x25));
22641595Ssklower 		if (lcp -> lcd_flags & X25_OLDSOCKADDR)
22741595Ssklower 			new_to_old (nam);
22841595Ssklower 		break;
22941595Ssklower 
23041595Ssklower 	case PRU_PEERADDR:
23141595Ssklower 		if (lcp -> lcd_state != DATA_TRANSFER)
23241595Ssklower 			return (ENOTCONN);
23341595Ssklower 		nam -> m_len = sizeof (struct sockaddr_x25);
23441595Ssklower 		bcopy (lcp -> lcd_craddr ? (caddr_t)lcp -> lcd_craddr :
23541595Ssklower 			(caddr_t)lcp -> lcd_ceaddr,
23641595Ssklower 			mtod (nam, caddr_t), sizeof (struct sockaddr_x25));
23741595Ssklower 		if (lcp -> lcd_flags & X25_OLDSOCKADDR)
23841595Ssklower 			new_to_old (nam);
23941595Ssklower 		break;
24041595Ssklower 
24141595Ssklower 	/*
24241595Ssklower 	 *  Receive INTERRUPT packet.
24341595Ssklower 	 */
24441595Ssklower 	case PRU_RCVOOB:
24545895Ssklower 		if (so -> so_options & SO_OOBINLINE) {
24645895Ssklower 			register struct mbuf *n  = so -> so_rcv.sb_mb;
24745895Ssklower 			if (n && n -> m_type == MT_OOBDATA) {
24845895Ssklower 				unsigned len =  n -> m_pkthdr.len;
24945895Ssklower 				so -> so_rcv.sb_mb = n -> m_nextpkt;
25045895Ssklower 				if (len !=  n -> m_len &&
25147261Ssklower 				    (n = m_pullup (n, len)) == 0)
25245895Ssklower 					break;
25345895Ssklower 				m -> m_len = len;
25447261Ssklower 				bcopy (mtod (m, caddr_t), mtod (n, caddr_t), len);
25547261Ssklower 				m_freem (n);
25645895Ssklower 			}
25745895Ssklower 			break;
25845895Ssklower 		}
25941595Ssklower 		m -> m_len = 1;
26041595Ssklower 		*mtod (m, char *) = lcp -> lcd_intrdata;
26141595Ssklower 		break;
26241595Ssklower 
26341595Ssklower 	default:
26441595Ssklower 		panic ("pk_usrreq");
26541595Ssklower 	}
26641936Ssklower release:
26741936Ssklower 	if (control != NULL)
26847261Ssklower 		m_freem (control);
26941595Ssklower 	return (error);
27041595Ssklower }
27141595Ssklower 
27242277Ssklower /*
27342277Ssklower  * If you want to use UBC X.25 level 3 in conjunction with some
27445895Ssklower  * other X.25 level 2 driver, have the ifp -> if_ioctl routine
27549933Ssklower  * assign pk_start to ia -> ia_start when called with SIOCSIFCONF_X25.
27642277Ssklower  */
27742277Ssklower /* ARGSUSED */
pk_start(lcp)27842277Ssklower pk_start (lcp)
27942277Ssklower register struct pklcd *lcp;
28042277Ssklower {
28149027Ssklower 	pk_output (lcp);
28249027Ssklower 	return (0); /* XXX pk_output should return a value */
28342277Ssklower }
28442277Ssklower 
28549933Ssklower #ifndef _offsetof
28649933Ssklower #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
28749933Ssklower #endif
28849933Ssklower struct sockaddr_x25 pk_sockmask = {
28957024Ssklower 	_offsetof(struct sockaddr_x25, x25_addr[0]),      /* x25_len */
29057024Ssklower 	0,                                                /* x25_family */
29157024Ssklower 	-1,                                               /* x25_net id */
29257024Ssklower };
29349933Ssklower 
29441595Ssklower /*ARGSUSED*/
29541595Ssklower pk_control (so, cmd, data, ifp)
29641595Ssklower struct socket *so;
297*68166Scgd u_long cmd;
29841595Ssklower caddr_t data;
29941595Ssklower register struct ifnet *ifp;
30041595Ssklower {
30142140Ssklower 	register struct ifreq_x25 *ifr = (struct ifreq_x25 *)data;
30241595Ssklower 	register struct ifaddr *ifa = 0;
30341936Ssklower 	register struct x25_ifaddr *ia = 0;
30442277Ssklower 	struct pklcd *dev_lcp = 0;
30545297Ssklower 	int error, s, old_maxlcn;
30641936Ssklower 	unsigned n;
30741595Ssklower 
30841595Ssklower 	/*
30941595Ssklower 	 * Find address for this interface, if it exists.
31041595Ssklower 	 */
31141595Ssklower 	if (ifp)
31245895Ssklower 		for (ifa = ifp -> if_addrlist; ifa; ifa = ifa -> ifa_next)
31345895Ssklower 			if (ifa -> ifa_addr -> sa_family == AF_CCITT)
31441595Ssklower 				break;
31541595Ssklower 
31641936Ssklower 	ia = (struct x25_ifaddr *)ifa;
31741595Ssklower 	switch (cmd) {
31842140Ssklower 	case SIOCGIFCONF_X25:
31941595Ssklower 		if (ifa == 0)
32041595Ssklower 			return (EADDRNOTAVAIL);
32145895Ssklower 		ifr -> ifr_xc = ia -> ia_xc;
32241595Ssklower 		return (0);
32341595Ssklower 
32442140Ssklower 	case SIOCSIFCONF_X25:
32550241Ssklower 		if ((so->so_state & SS_PRIV) == 0)
32650241Ssklower 			return (EPERM);
32741595Ssklower 		if (ifp == 0)
32847261Ssklower 			panic ("pk_control");
32941595Ssklower 		if (ifa == (struct ifaddr *)0) {
33041595Ssklower 			register struct mbuf *m;
33141595Ssklower 
33242277Ssklower 			MALLOC(ia, struct x25_ifaddr *, sizeof (*ia),
33342277Ssklower 				M_IFADDR, M_WAITOK);
33442277Ssklower 			if (ia == 0)
33541595Ssklower 				return (ENOBUFS);
33647261Ssklower 			bzero ((caddr_t)ia, sizeof (*ia));
33745895Ssklower 			if (ifa = ifp -> if_addrlist) {
33845895Ssklower 				for ( ; ifa -> ifa_next; ifa = ifa -> ifa_next)
33941595Ssklower 					;
34045895Ssklower 				ifa -> ifa_next = &ia -> ia_ifa;
34141595Ssklower 			} else
34245895Ssklower 				ifp -> if_addrlist = &ia -> ia_ifa;
34345895Ssklower 			ifa = &ia -> ia_ifa;
34449933Ssklower 			ifa -> ifa_netmask = (struct sockaddr *)&pk_sockmask;
34545895Ssklower 			ifa -> ifa_addr = (struct sockaddr *)&ia -> ia_xc.xc_addr;
34649933Ssklower 			ifa -> ifa_dstaddr = (struct sockaddr *)&ia -> ia_dstaddr; /* XXX */
34745895Ssklower 			ia -> ia_ifp = ifp;
34849933Ssklower 			ia -> ia_dstaddr.x25_family = AF_CCITT;
34949933Ssklower 			ia -> ia_dstaddr.x25_len = pk_sockmask.x25_len;
35057024Ssklower 		} else if (ISISO8802(ifp) == 0) {
35149933Ssklower 			rtinit (ifa, (int)RTM_DELETE, 0);
35241595Ssklower 		}
35345895Ssklower 		old_maxlcn = ia -> ia_maxlcn;
35445895Ssklower 		ia -> ia_xc = ifr -> ifr_xc;
35549933Ssklower 		ia -> ia_dstaddr.x25_net = ia -> ia_xc.xc_addr.x25_net;
35649933Ssklower 		if (ia -> ia_maxlcn != old_maxlcn && old_maxlcn != 0) {
35749933Ssklower 			/* VERY messy XXX */
35849933Ssklower 			register struct pkcb *pkp;
35957024Ssklower 			FOR_ALL_PKCBS(pkp)
36049933Ssklower 				if (pkp -> pk_ia == ia)
36149933Ssklower 					pk_resize (pkp);
36241936Ssklower 		}
36341595Ssklower 		/*
36441595Ssklower 		 * Give the interface a chance to initialize if this
36557024Ssklower p		 * is its first address, and to validate the address.
36641595Ssklower 		 */
36749933Ssklower 		ia -> ia_start = pk_start;
36841936Ssklower 		s = splimp();
36945895Ssklower 		if (ifp -> if_ioctl)
37057024Ssklower 			error = (*ifp -> if_ioctl)(ifp, SIOCSIFCONF_X25,
37157024Ssklower 						   (caddr_t) ifa);
37245297Ssklower 		if (error)
37345895Ssklower 			ifp -> if_flags &= ~IFF_UP;
37457024Ssklower 		else if (ISISO8802(ifp) == 0)
37549933Ssklower 			error = rtinit (ifa, (int)RTM_ADD, RTF_UP);
37645895Ssklower 		splx (s);
37741936Ssklower 		return (error);
37841595Ssklower 
37941595Ssklower 	default:
38045895Ssklower 		if (ifp == 0 || ifp -> if_ioctl == 0)
38141595Ssklower 			return (EOPNOTSUPP);
38245895Ssklower 		return ((*ifp -> if_ioctl)(ifp, cmd, data));
38341595Ssklower 	}
38441595Ssklower }
38541595Ssklower 
38647261Ssklower pk_ctloutput (cmd, so, level, optname, mp)
38745165Ssklower struct socket *so;
38845165Ssklower struct mbuf **mp;
38945165Ssklower int cmd, level, optname;
39045165Ssklower {
39145165Ssklower 	register struct mbuf *m = *mp;
39245895Ssklower 	register struct pklcd *lcp = (struct pklcd *) so -> so_pcb;
39349933Ssklower 	int error = EOPNOTSUPP;
39445165Ssklower 
39549933Ssklower 	if (m == 0)
39649933Ssklower 		return (EINVAL);
39745165Ssklower 	if (cmd == PRCO_SETOPT) switch (optname) {
39849933Ssklower 	case PK_FACILITIES:
39945165Ssklower 		if (m == 0)
40045165Ssklower 			return (EINVAL);
40149933Ssklower 		lcp -> lcd_facilities = m;
40249933Ssklower 		*mp = 0;
40349933Ssklower 		return (0);
40449933Ssklower 
40549933Ssklower 	case PK_ACCTFILE:
40650241Ssklower 		if ((so->so_state & SS_PRIV) == 0)
40750241Ssklower 			error = EPERM;
40850241Ssklower 		else if (m -> m_len)
40947261Ssklower 			error = pk_accton (mtod (m, char *));
41045165Ssklower 		else
41145895Ssklower 			error = pk_accton ((char *)0);
41249933Ssklower 		break;
41345895Ssklower 
41449933Ssklower 	case PK_RTATTACH:
41549933Ssklower 		error = pk_rtattach (so, m);
41649933Ssklower 		break;
41749933Ssklower 
41849933Ssklower 	case PK_PRLISTEN:
41949933Ssklower 		error = pk_user_protolisten (mtod (m, u_char *));
42045165Ssklower 	}
42145165Ssklower 	if (*mp) {
42245895Ssklower 		(void) m_freem (*mp);
42345165Ssklower 		*mp = 0;
42445165Ssklower 	}
42550156Ssklower 	return (error);
42645165Ssklower 
42745165Ssklower }
42845165Ssklower 
42949933Ssklower 
43041595Ssklower /*
43141595Ssklower  * Do an in-place conversion of an "old style"
43241595Ssklower  * socket address to the new style
43341595Ssklower  */
43441595Ssklower 
43541595Ssklower static
old_to_new(m)43641595Ssklower old_to_new (m)
43741595Ssklower register struct mbuf *m;
43841595Ssklower {
43941595Ssklower 	register struct x25_sockaddr *oldp;
44041595Ssklower 	register struct sockaddr_x25 *newp;
44141595Ssklower 	register char *ocp, *ncp;
44241595Ssklower 	struct sockaddr_x25 new;
44341595Ssklower 
44441595Ssklower 	oldp = mtod (m, struct x25_sockaddr *);
44541595Ssklower 	newp = &new;
44641595Ssklower 	bzero ((caddr_t)newp, sizeof (*newp));
44741595Ssklower 
44841595Ssklower 	newp -> x25_family = AF_CCITT;
44948753Ssklower 	newp -> x25_len = sizeof(*newp);
45045895Ssklower 	newp -> x25_opts.op_flags = (oldp -> xaddr_facilities & X25_REVERSE_CHARGE)
45141595Ssklower 		| X25_MQBIT | X25_OLDSOCKADDR;
45241595Ssklower 	if (oldp -> xaddr_facilities & XS_HIPRIO)	/* Datapac specific */
45341595Ssklower 		newp -> x25_opts.op_psize = X25_PS128;
45441595Ssklower 	bcopy ((caddr_t)oldp -> xaddr_addr, newp -> x25_addr,
45548753Ssklower 	       (unsigned)min (oldp -> xaddr_len, sizeof (newp -> x25_addr) - 1));
45648753Ssklower 	if (bcmp ((caddr_t)oldp -> xaddr_proto, newp -> x25_udata, 4) != 0) {
45748753Ssklower 		bcopy ((caddr_t)oldp -> xaddr_proto, newp -> x25_udata, 4);
45848753Ssklower 		newp -> x25_udlen = 4;
45948753Ssklower 	}
46041595Ssklower 	ocp = (caddr_t)oldp -> xaddr_userdata;
46141595Ssklower 	ncp = newp -> x25_udata + 4;
46241595Ssklower 	while (*ocp && ocp < (caddr_t)oldp -> xaddr_userdata + 12) {
46348753Ssklower 		if (newp -> x25_udlen == 0)
46448753Ssklower 			newp -> x25_udlen = 4;
46541595Ssklower 		*ncp++ = *ocp++;
46641595Ssklower 		newp -> x25_udlen++;
46741595Ssklower 	}
46841595Ssklower 	bcopy ((caddr_t)newp, mtod (m, char *), sizeof (*newp));
46945895Ssklower 	m -> m_len = sizeof (*newp);
47041595Ssklower }
47141595Ssklower 
47241595Ssklower /*
47341595Ssklower  * Do an in-place conversion of a new style
47441595Ssklower  * socket address to the old style
47541595Ssklower  */
47641595Ssklower 
47741595Ssklower static
new_to_old(m)47841595Ssklower new_to_old (m)
47941595Ssklower register struct mbuf *m;
48041595Ssklower {
48141595Ssklower 	register struct x25_sockaddr *oldp;
48241595Ssklower 	register struct sockaddr_x25 *newp;
48341595Ssklower 	register char *ocp, *ncp;
48441595Ssklower 	struct x25_sockaddr old;
48541595Ssklower 
48641595Ssklower 	oldp = &old;
48741595Ssklower 	newp = mtod (m, struct sockaddr_x25 *);
48841595Ssklower 	bzero ((caddr_t)oldp, sizeof (*oldp));
48941595Ssklower 
49041595Ssklower 	oldp -> xaddr_facilities = newp -> x25_opts.op_flags & X25_REVERSE_CHARGE;
49141595Ssklower 	if (newp -> x25_opts.op_psize == X25_PS128)
49241595Ssklower 		oldp -> xaddr_facilities |= XS_HIPRIO;	/* Datapac specific */
49341595Ssklower 	ocp = (char *)oldp -> xaddr_addr;
49441595Ssklower 	ncp = newp -> x25_addr;
49541595Ssklower 	while (*ncp) {
49641595Ssklower 		*ocp++ = *ncp++;
49741595Ssklower 		oldp -> xaddr_len++;
49841595Ssklower 	}
49941595Ssklower 
50041595Ssklower 	bcopy (newp -> x25_udata, (caddr_t)oldp -> xaddr_proto, 4);
50148753Ssklower 	if (newp -> x25_udlen > 4)
50248753Ssklower 		bcopy (newp -> x25_udata + 4, (caddr_t)oldp -> xaddr_userdata,
50348753Ssklower 			(unsigned)(newp -> x25_udlen - 4));
50441595Ssklower 
50541595Ssklower 	bcopy ((caddr_t)oldp, mtod (m, char *), sizeof (*oldp));
50641595Ssklower 	m -> m_len = sizeof (*oldp);
50741595Ssklower }
50841595Ssklower 
50945895Ssklower 
51045895Ssklower pk_checksockaddr (m)
51145895Ssklower struct mbuf *m;
51245895Ssklower {
51345895Ssklower 	register struct sockaddr_x25 *sa = mtod (m, struct sockaddr_x25 *);
51445895Ssklower 	register char *cp;
51545895Ssklower 
51645895Ssklower 	if (m -> m_len != sizeof (struct sockaddr_x25))
51745895Ssklower 		return (1);
51845895Ssklower 	if (sa -> x25_family != AF_CCITT ||
51945895Ssklower 		sa -> x25_udlen > sizeof (sa -> x25_udata))
52045895Ssklower 		return (1);
52145895Ssklower 	for (cp = sa -> x25_addr; *cp; cp++) {
52245895Ssklower 		if (*cp < '0' || *cp > '9' ||
52345895Ssklower 			cp >= &sa -> x25_addr[sizeof (sa -> x25_addr) - 1])
52445895Ssklower 			return (1);
52545895Ssklower 	}
52645895Ssklower 	return (0);
52745895Ssklower }
52849027Ssklower 
52941595Ssklower pk_send (lcp, m)
53045297Ssklower struct pklcd *lcp;
53141595Ssklower register struct mbuf *m;
53241595Ssklower {
53345895Ssklower 	int mqbit = 0, error = 0;
53445895Ssklower 	register struct x25_packet *xp;
53549027Ssklower 	register struct socket *so;
53641595Ssklower 
53745895Ssklower 	if (m -> m_type == MT_OOBDATA) {
53845895Ssklower 		if (lcp -> lcd_intrconf_pending)
53945895Ssklower 			error = ETOOMANYREFS;
54045895Ssklower 		if (m -> m_pkthdr.len > 32)
54145895Ssklower 			error = EMSGSIZE;
54245895Ssklower 		M_PREPEND(m, PKHEADERLN, M_WAITOK);
54345895Ssklower 		if (m == 0 || error)
54445895Ssklower 			goto bad;
54545895Ssklower 		*(mtod (m, octet *)) = 0;
54645895Ssklower 		xp = mtod (m, struct x25_packet *);
54757024Ssklower 		X25SBITS(xp -> bits, fmt_identifier, 1);
54845895Ssklower 		xp -> packet_type = X25_INTERRUPT;
54945895Ssklower 		SET_LCN(xp, lcp -> lcd_lcn);
55049027Ssklower 		sbinsertoob ( (so = lcp -> lcd_so) ?
55149027Ssklower 			&so -> so_snd : &lcp -> lcd_sb, m);
55249027Ssklower 		goto send;
55345895Ssklower 	}
55441595Ssklower 	/*
55541595Ssklower 	 * Application has elected (at call setup time) to prepend
55641595Ssklower 	 * a control byte to each packet written indicating m-bit
55741595Ssklower 	 * and q-bit status.  Examine and then discard this byte.
55841595Ssklower 	 */
55941595Ssklower 	if (lcp -> lcd_flags & X25_MQBIT) {
56041595Ssklower 		if (m -> m_len < 1) {
56145297Ssklower 			m_freem (m);
56241595Ssklower 			return (EMSGSIZE);
56341595Ssklower 		}
56445895Ssklower 		mqbit = *(mtod (m, u_char *));
56541595Ssklower 		m -> m_len--;
56641936Ssklower 		m -> m_data++;
56745297Ssklower 		m -> m_pkthdr.len--;
56841595Ssklower 	}
56949027Ssklower 	error = pk_fragment (lcp, m, mqbit & 0x80, mqbit & 0x40, 1);
57049027Ssklower send:
57149027Ssklower 	if (error == 0 && lcp -> lcd_state == DATA_TRANSFER)
57249027Ssklower 		lcp -> lcd_send (lcp); /* XXXXXXXXX fix pk_output!!! */
57345297Ssklower 	return (error);
57445895Ssklower bad:
57545895Ssklower 	if (m)
57645895Ssklower 		m_freem (m);
57745895Ssklower 	return (error);
57841595Ssklower }
579