xref: /csrg-svn/sys/netccitt/pk_usrreq.c (revision 49027)
141709Ssklower /*
241709Ssklower  * Copyright (c) University of British Columbia, 1984
341709Ssklower  * Copyright (c) 1990 The Regents of the University of California.
441709Ssklower  * All rights reserved.
541709Ssklower  *
641709Ssklower  * This code is derived from software contributed to Berkeley by
741709Ssklower  * the Laboratory for Computation Vision and the Computer Science Department
841709Ssklower  * of the University of British Columbia.
941709Ssklower  *
1041709Ssklower  * %sccs.include.redist.c%
1141709Ssklower  *
12*49027Ssklower  *	@(#)pk_usrreq.c	7.13 (Berkeley) 05/03/91
1341709Ssklower  */
1441595Ssklower 
1542140Ssklower #include "param.h"
1642140Ssklower #include "systm.h"
1742140Ssklower #include "mbuf.h"
1842140Ssklower #include "socket.h"
1942140Ssklower #include "protosw.h"
2042140Ssklower #include "socketvar.h"
2142140Ssklower #include "errno.h"
2241595Ssklower #include "ioctl.h"
2341595Ssklower #include "user.h"
2441595Ssklower #include "stat.h"
2541595Ssklower 
2642140Ssklower #include "../net/if.h"
2741595Ssklower 
2842140Ssklower #include "x25.h"
2942140Ssklower #include "pk.h"
3042140Ssklower #include "pk_var.h"
3142140Ssklower 
3241595Ssklower /*
3341595Ssklower  *
3441595Ssklower  *  X.25 Packet level protocol interface to socket abstraction.
3541595Ssklower  *
3641595Ssklower  *  Process an X.25 user request on a logical channel.  If this is a send
3741595Ssklower  *  request then m is the mbuf chain of the send data. If this is a timer
3841595Ssklower  *  expiration (called from the software clock routine) them timertype is
3941595Ssklower  *  the particular timer.
4041595Ssklower  *
4141595Ssklower  */
4241595Ssklower 
4341936Ssklower pk_usrreq (so, req, m, nam, control)
4441595Ssklower struct socket *so;
4541595Ssklower int req;
4641595Ssklower register struct mbuf *m, *nam;
4741936Ssklower struct mbuf *control;
4841595Ssklower {
4941595Ssklower 	register struct pklcd *lcp = (struct pklcd *) so -> so_pcb;
5041936Ssklower 	register int error = 0;
5141595Ssklower 
5241936Ssklower 	if (req == PRU_CONTROL)
5347261Ssklower 		return (pk_control (so, (int)m, (caddr_t)nam,
5441936Ssklower 			(struct ifnet *)control));
5545895Ssklower 	if (control && control -> m_len) {
5641936Ssklower 		error = EINVAL;
5741936Ssklower 		goto release;
5841595Ssklower 	}
5941936Ssklower 	if (lcp == NULL && req != PRU_ATTACH) {
6041936Ssklower 		error = EINVAL;
6141936Ssklower 		goto release;
6241595Ssklower 	}
6341595Ssklower 
6441595Ssklower /*
6541595Ssklower 	pk_trace (pkcbhead, TR_USER, (struct pklcd *)0,
6641595Ssklower 		req, (struct x25_packet *)0);
6741595Ssklower */
6841595Ssklower 
6941595Ssklower 	switch (req) {
7041595Ssklower 	/*
7141595Ssklower 	 *  X.25 attaches to socket via PRU_ATTACH and allocates a logical
7241595Ssklower 	 *  channel descriptor.  If the socket is to  receive connections,
7341595Ssklower 	 *  then the LISTEN state is entered.
7441595Ssklower 	 */
7541595Ssklower 	case PRU_ATTACH:
7641595Ssklower 		if (lcp) {
7741595Ssklower 			error = EISCONN;
7841595Ssklower 			/* Socket already connected. */
7941595Ssklower 			break;
8041595Ssklower 		}
8145165Ssklower 		lcp = pk_attach (so);
8245165Ssklower 		if (lcp == 0)
8345165Ssklower 			error = ENOBUFS;
8441595Ssklower 		break;
8541595Ssklower 
8641595Ssklower 	/*
8741595Ssklower 	 *  Detach a logical channel from the socket. If the state of the
8841595Ssklower 	 *  channel is embryonic, simply discard it. Otherwise we have to
8941595Ssklower 	 *  initiate a PRU_DISCONNECT which will finish later.
9041595Ssklower 	 */
9141595Ssklower 	case PRU_DETACH:
9241595Ssklower 		pk_disconnect (lcp);
9341595Ssklower 		break;
9441595Ssklower 
9541595Ssklower 	/*
9641595Ssklower 	 *  Give the socket an address.
9741595Ssklower 	 */
9841595Ssklower 	case PRU_BIND:
9941595Ssklower 		if (nam -> m_len == sizeof (struct x25_sockaddr))
10041595Ssklower 			old_to_new (nam);
10141595Ssklower 		error = pk_bind (lcp, nam);
10241595Ssklower 		break;
10341595Ssklower 
10441595Ssklower 	/*
10541595Ssklower 	 *  Prepare to accept connections.
10641595Ssklower 	 */
10741595Ssklower 	case PRU_LISTEN:
10845895Ssklower 		error = pk_listen (lcp);
10941595Ssklower 		break;
11041595Ssklower 
11141595Ssklower 	/*
11241595Ssklower 	 *  Initiate a CALL REQUEST to peer entity. Enter state SENT_CALL
11341595Ssklower 	 *  and mark the socket as connecting. Set timer waiting for
11441595Ssklower 	 *  CALL ACCEPT or CLEAR.
11541595Ssklower 	 */
11641595Ssklower 	case PRU_CONNECT:
11741595Ssklower 		if (nam -> m_len == sizeof (struct x25_sockaddr))
11841595Ssklower 			old_to_new (nam);
11945895Ssklower 		if (pk_checksockaddr (nam))
12045895Ssklower 			return (EINVAL);
12145895Ssklower 		error = pk_connect (lcp, mtod (nam, struct sockaddr_x25 *));
12241595Ssklower 		break;
12341595Ssklower 
12441595Ssklower 	/*
12541595Ssklower 	 *  Initiate a disconnect to peer entity via a CLEAR REQUEST packet.
12641595Ssklower 	 *  The socket will be disconnected when we receive a confirmation
12741595Ssklower 	 *  or a clear collision.
12841595Ssklower 	 */
12941595Ssklower 	case PRU_DISCONNECT:
13041595Ssklower 		pk_disconnect (lcp);
13141595Ssklower 		break;
13241595Ssklower 
13341595Ssklower 	/*
13441595Ssklower 	 *  Accept an INCOMING CALL. Most of the work has already been done
13541595Ssklower 	 *  by pk_input. Just return the callers address to the user.
13641595Ssklower 	 */
13741595Ssklower 	case PRU_ACCEPT:
13841595Ssklower 		if (lcp -> lcd_craddr == NULL)
13941595Ssklower 			break;
14041595Ssklower 		bcopy ((caddr_t)lcp -> lcd_craddr, mtod (nam, caddr_t),
14141595Ssklower 			sizeof (struct sockaddr_x25));
14241595Ssklower 		nam -> m_len = sizeof (struct sockaddr_x25);
14341595Ssklower 		if (lcp -> lcd_flags & X25_OLDSOCKADDR)
14441595Ssklower 			new_to_old (nam);
14541595Ssklower 		break;
14641595Ssklower 
14741595Ssklower 	/*
14841595Ssklower 	 *  After a receive, we should send a RR.
14941595Ssklower 	 */
15041595Ssklower 	case PRU_RCVD:
15141595Ssklower 		lcp -> lcd_rxcnt++;
15241595Ssklower 		lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RR);
15341595Ssklower 		pk_output (lcp);
15447261Ssklower 		/*pk_flowcontrol (lcp, sbspace (&so -> so_rcv) <= 0, 1);*/
15541595Ssklower 		break;
15641595Ssklower 
15741595Ssklower 	/*
15845895Ssklower 	 *  Send INTERRUPT packet.
15945895Ssklower 	 */
16045895Ssklower 	case PRU_SENDOOB:
16145895Ssklower 		if (m == 0) {
16245895Ssklower 			MGETHDR(m, M_WAITOK, MT_OOBDATA);
16345895Ssklower 			m -> m_pkthdr.len = m -> m_len = 1;
16447261Ssklower 			*mtod (m, octet *) = 0;
16545895Ssklower 		}
16645895Ssklower 		if (m -> m_pkthdr.len > 32) {
16747261Ssklower 			m_freem (m);
16845895Ssklower 			error = EMSGSIZE;
16945895Ssklower 			break;
17045895Ssklower 		}
17145895Ssklower 		MCHTYPE(m, MT_OOBDATA);
17245895Ssklower 		/* FALLTHROUGH */
17345895Ssklower 
17445895Ssklower 	/*
17541595Ssklower 	 *  Do send by placing data on the socket output queue.
17641595Ssklower 	 */
17741595Ssklower 	case PRU_SEND:
17845895Ssklower 		if (control) {
17947261Ssklower 			register struct cmsghdr *ch = mtod (m, struct cmsghdr *);
18045895Ssklower 			control -> m_len -= sizeof (*ch);
18145895Ssklower 			control -> m_data += sizeof (*ch);
18247261Ssklower 			pk_ctloutput (PRCO_SETOPT, so, ch -> cmsg_level,
18345895Ssklower 					ch -> cmsg_type, &control);
18445895Ssklower 		}
18545895Ssklower 		if (m)
18645895Ssklower 			error = pk_send (lcp, m);
18741595Ssklower 		break;
18841595Ssklower 
18941595Ssklower 	/*
19041595Ssklower 	 *  Abort a virtual circuit. For example all completed calls
19141595Ssklower 	 *  waiting acceptance.
19241595Ssklower 	 */
19341595Ssklower 	case PRU_ABORT:
19441595Ssklower 		pk_disconnect (lcp);
19541595Ssklower 		break;
19641595Ssklower 
19741595Ssklower 	/* Begin unimplemented hooks. */
19841595Ssklower 
19941595Ssklower 	case PRU_SHUTDOWN:
20041595Ssklower 		error = EOPNOTSUPP;
20141595Ssklower 		break;
20241595Ssklower 
20341595Ssklower 	case PRU_CONTROL:
20441595Ssklower 		error = EOPNOTSUPP;
20541595Ssklower 		break;
20641595Ssklower 
20741595Ssklower 	case PRU_SENSE:
20841595Ssklower #ifdef BSD4_3
20941595Ssklower 		((struct stat *)m) -> st_blksize = so -> so_snd.sb_hiwat;
21041595Ssklower #else
21141595Ssklower 		error = EOPNOTSUPP;
21241595Ssklower #endif
21341595Ssklower 		break;
21441595Ssklower 
21541595Ssklower 	/* End unimplemented hooks. */
21641595Ssklower 
21741595Ssklower 	case PRU_SOCKADDR:
21841595Ssklower 		if (lcp -> lcd_ceaddr == 0)
21941595Ssklower 			return (EADDRNOTAVAIL);
22041595Ssklower 		nam -> m_len = sizeof (struct sockaddr_x25);
22141595Ssklower 		bcopy ((caddr_t)lcp -> lcd_ceaddr, mtod (nam, caddr_t),
22241595Ssklower 			sizeof (struct sockaddr_x25));
22341595Ssklower 		if (lcp -> lcd_flags & X25_OLDSOCKADDR)
22441595Ssklower 			new_to_old (nam);
22541595Ssklower 		break;
22641595Ssklower 
22741595Ssklower 	case PRU_PEERADDR:
22841595Ssklower 		if (lcp -> lcd_state != DATA_TRANSFER)
22941595Ssklower 			return (ENOTCONN);
23041595Ssklower 		nam -> m_len = sizeof (struct sockaddr_x25);
23141595Ssklower 		bcopy (lcp -> lcd_craddr ? (caddr_t)lcp -> lcd_craddr :
23241595Ssklower 			(caddr_t)lcp -> lcd_ceaddr,
23341595Ssklower 			mtod (nam, caddr_t), sizeof (struct sockaddr_x25));
23441595Ssklower 		if (lcp -> lcd_flags & X25_OLDSOCKADDR)
23541595Ssklower 			new_to_old (nam);
23641595Ssklower 		break;
23741595Ssklower 
23841595Ssklower 	/*
23941595Ssklower 	 *  Receive INTERRUPT packet.
24041595Ssklower 	 */
24141595Ssklower 	case PRU_RCVOOB:
24245895Ssklower 		if (so -> so_options & SO_OOBINLINE) {
24345895Ssklower 			register struct mbuf *n  = so -> so_rcv.sb_mb;
24445895Ssklower 			if (n && n -> m_type == MT_OOBDATA) {
24545895Ssklower 				unsigned len =  n -> m_pkthdr.len;
24645895Ssklower 				so -> so_rcv.sb_mb = n -> m_nextpkt;
24745895Ssklower 				if (len !=  n -> m_len &&
24847261Ssklower 				    (n = m_pullup (n, len)) == 0)
24945895Ssklower 					break;
25045895Ssklower 				m -> m_len = len;
25147261Ssklower 				bcopy (mtod (m, caddr_t), mtod (n, caddr_t), len);
25247261Ssklower 				m_freem (n);
25345895Ssklower 			}
25445895Ssklower 			break;
25545895Ssklower 		}
25641595Ssklower 		m -> m_len = 1;
25741595Ssklower 		*mtod (m, char *) = lcp -> lcd_intrdata;
25841595Ssklower 		break;
25941595Ssklower 
26041595Ssklower 	default:
26141595Ssklower 		panic ("pk_usrreq");
26241595Ssklower 	}
26341936Ssklower release:
26441936Ssklower 	if (control != NULL)
26547261Ssklower 		m_freem (control);
26641595Ssklower 	return (error);
26741595Ssklower }
26841595Ssklower 
26942277Ssklower /*
27042277Ssklower  * If you want to use UBC X.25 level 3 in conjunction with some
27145895Ssklower  * other X.25 level 2 driver, have the ifp -> if_ioctl routine
27242277Ssklower  * assign pk_start to pkp -> pk_start when called with SIOCSIFCONF_X25.
27342277Ssklower  */
27442277Ssklower /* ARGSUSED */
27542277Ssklower pk_start (lcp)
27642277Ssklower register struct pklcd *lcp;
27742277Ssklower {
278*49027Ssklower 	pk_output (lcp);
279*49027Ssklower 	return (0); /* XXX pk_output should return a value */
28042277Ssklower }
28142277Ssklower 
28241595Ssklower /*ARGSUSED*/
28341595Ssklower pk_control (so, cmd, data, ifp)
28441595Ssklower struct socket *so;
28541595Ssklower int cmd;
28641595Ssklower caddr_t data;
28741595Ssklower register struct ifnet *ifp;
28841595Ssklower {
28942140Ssklower 	register struct ifreq_x25 *ifr = (struct ifreq_x25 *)data;
29041595Ssklower 	register struct ifaddr *ifa = 0;
29141936Ssklower 	register struct x25_ifaddr *ia = 0;
29242277Ssklower 	struct pklcd *dev_lcp = 0;
29345297Ssklower 	int error, s, old_maxlcn;
29441936Ssklower 	unsigned n;
29541595Ssklower 
29641595Ssklower 	/*
29741595Ssklower 	 * Find address for this interface, if it exists.
29841595Ssklower 	 */
29941595Ssklower 	if (ifp)
30045895Ssklower 		for (ifa = ifp -> if_addrlist; ifa; ifa = ifa -> ifa_next)
30145895Ssklower 			if (ifa -> ifa_addr -> sa_family == AF_CCITT)
30241595Ssklower 				break;
30341595Ssklower 
30441936Ssklower 	ia = (struct x25_ifaddr *)ifa;
30541595Ssklower 	switch (cmd) {
30642140Ssklower 	case SIOCGIFCONF_X25:
30741595Ssklower 		if (ifa == 0)
30841595Ssklower 			return (EADDRNOTAVAIL);
30945895Ssklower 		ifr -> ifr_xc = ia -> ia_xc;
31041595Ssklower 		return (0);
31141595Ssklower 
31242140Ssklower 	case SIOCSIFCONF_X25:
31347261Ssklower 		if (error = suser (u.u_cred, &u.u_acflag))
31445165Ssklower 			return (error);
31541595Ssklower 		if (ifp == 0)
31647261Ssklower 			panic ("pk_control");
31741595Ssklower 		if (ifa == (struct ifaddr *)0) {
31841595Ssklower 			register struct mbuf *m;
31941595Ssklower 
32042277Ssklower 			MALLOC(ia, struct x25_ifaddr *, sizeof (*ia),
32142277Ssklower 				M_IFADDR, M_WAITOK);
32242277Ssklower 			if (ia == 0)
32341595Ssklower 				return (ENOBUFS);
32447261Ssklower 			bzero ((caddr_t)ia, sizeof (*ia));
32545895Ssklower 			if (ifa = ifp -> if_addrlist) {
32645895Ssklower 				for ( ; ifa -> ifa_next; ifa = ifa -> ifa_next)
32741595Ssklower 					;
32845895Ssklower 				ifa -> ifa_next = &ia -> ia_ifa;
32941595Ssklower 			} else
33045895Ssklower 				ifp -> if_addrlist = &ia -> ia_ifa;
33145895Ssklower 			ifa = &ia -> ia_ifa;
33245895Ssklower 			ifa -> ifa_netmask = (struct sockaddr *)&ia -> ia_sockmask;
33345895Ssklower 			ifa -> ifa_addr = (struct sockaddr *)&ia -> ia_xc.xc_addr;
33445895Ssklower 			ia -> ia_xcp = &ia -> ia_xc;
33545895Ssklower 			ia -> ia_ifp = ifp;
33645895Ssklower 			ia -> ia_pkcb.pk_ia = ia;
33745895Ssklower 			ia -> ia_pkcb.pk_next = pkcbhead;
33845895Ssklower 			ia -> ia_pkcb.pk_state = DTE_WAITING;
33945895Ssklower 			ia -> ia_pkcb.pk_start = pk_start;
34045895Ssklower 			pkcbhead = &ia -> ia_pkcb;
34141595Ssklower 		}
34245895Ssklower 		old_maxlcn = ia -> ia_maxlcn;
34345895Ssklower 		ia -> ia_xc = ifr -> ifr_xc;
34445895Ssklower 		if (ia -> ia_chan && (ia -> ia_maxlcn != old_maxlcn)) {
34547261Ssklower 			pk_restart (&ia -> ia_pkcb, X25_RESTART_NETWORK_CONGESTION);
34645895Ssklower 			dev_lcp = ia -> ia_chan[0];
34747261Ssklower 			free ((caddr_t)ia -> ia_chan, M_IFADDR);
34845895Ssklower 			ia -> ia_chan = 0;
34941936Ssklower 		}
35045895Ssklower 		if (ia -> ia_chan == 0) {
35147261Ssklower 			n = (ia -> ia_maxlcn + 1) * sizeof (struct pklcd *);
35247261Ssklower 			ia -> ia_chan = (struct pklcd **) malloc (n, M_IFADDR, M_WAITOK);
35345895Ssklower 			if (ia -> ia_chan) {
35447261Ssklower 				bzero ((caddr_t)ia -> ia_chan, n);
35542277Ssklower 				if (dev_lcp == 0)
35647261Ssklower 					dev_lcp = pk_attach ((struct socket *)0);
35745895Ssklower 				ia -> ia_chan[0] = dev_lcp;
35845895Ssklower 				dev_lcp -> lcd_state = READY;
35945895Ssklower 				dev_lcp -> lcd_pkp = &ia -> ia_pkcb;
36042277Ssklower 			} else {
36142277Ssklower 				if (dev_lcp)
36247261Ssklower 					pk_close (dev_lcp);
36342277Ssklower 				return (ENOBUFS);
36442277Ssklower 			}
36542140Ssklower 		}
36641595Ssklower 		/*
36741595Ssklower 		 * Give the interface a chance to initialize if this
36841595Ssklower 		 * is its first address, and to validate the address.
36941595Ssklower 		 */
37041936Ssklower 		s = splimp();
37145895Ssklower 		if (ifp -> if_ioctl)
37245895Ssklower 			error = (*ifp -> if_ioctl)(ifp, SIOCSIFCONF_X25, ifa);
37345297Ssklower 		if (error)
37445895Ssklower 			ifp -> if_flags &= ~IFF_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;
39245165Ssklower 	int error;
39345165Ssklower 
39445165Ssklower 	if (cmd == PRCO_SETOPT) switch (optname) {
39545165Ssklower 	case PK_ACCTFILE:
39645165Ssklower 		if (m == 0)
39745165Ssklower 			return (EINVAL);
39845895Ssklower 		if (m -> m_len)
39947261Ssklower 			error = pk_accton (mtod (m, char *));
40045165Ssklower 		else
40145895Ssklower 			error = pk_accton ((char *)0);
40245895Ssklower 		(void) m_freem (m);
40345165Ssklower 		*mp = 0;
40445165Ssklower 		return (error);
40545895Ssklower 
40645895Ssklower 	case PK_FACILITIES:
40745895Ssklower 		if (m == 0)
40845895Ssklower 			return (EINVAL);
40945895Ssklower 		lcp -> lcd_facilities = m;
41045895Ssklower 		*mp = 0;
41145895Ssklower 		return (0);
41245165Ssklower 	}
41345165Ssklower 	if (*mp) {
41445895Ssklower 		(void) m_freem (*mp);
41545165Ssklower 		*mp = 0;
41645165Ssklower 	}
41745165Ssklower 	return (EOPNOTSUPP);
41845165Ssklower 
41945165Ssklower }
42045165Ssklower 
42141595Ssklower /*
42241595Ssklower  * Do an in-place conversion of an "old style"
42341595Ssklower  * socket address to the new style
42441595Ssklower  */
42541595Ssklower 
42641595Ssklower static
42741595Ssklower old_to_new (m)
42841595Ssklower register struct mbuf *m;
42941595Ssklower {
43041595Ssklower 	register struct x25_sockaddr *oldp;
43141595Ssklower 	register struct sockaddr_x25 *newp;
43241595Ssklower 	register char *ocp, *ncp;
43341595Ssklower 	struct sockaddr_x25 new;
43441595Ssklower 
43541595Ssklower 	oldp = mtod (m, struct x25_sockaddr *);
43641595Ssklower 	newp = &new;
43741595Ssklower 	bzero ((caddr_t)newp, sizeof (*newp));
43841595Ssklower 
43941595Ssklower 	newp -> x25_family = AF_CCITT;
44048753Ssklower 	newp -> x25_len = sizeof(*newp);
44145895Ssklower 	newp -> x25_opts.op_flags = (oldp -> xaddr_facilities & X25_REVERSE_CHARGE)
44241595Ssklower 		| X25_MQBIT | X25_OLDSOCKADDR;
44341595Ssklower 	if (oldp -> xaddr_facilities & XS_HIPRIO)	/* Datapac specific */
44441595Ssklower 		newp -> x25_opts.op_psize = X25_PS128;
44541595Ssklower 	bcopy ((caddr_t)oldp -> xaddr_addr, newp -> x25_addr,
44648753Ssklower 	       (unsigned)min (oldp -> xaddr_len, sizeof (newp -> x25_addr) - 1));
44748753Ssklower 	if (bcmp ((caddr_t)oldp -> xaddr_proto, newp -> x25_udata, 4) != 0) {
44848753Ssklower 		bcopy ((caddr_t)oldp -> xaddr_proto, newp -> x25_udata, 4);
44948753Ssklower 		newp -> x25_udlen = 4;
45048753Ssklower 	}
45141595Ssklower 	ocp = (caddr_t)oldp -> xaddr_userdata;
45241595Ssklower 	ncp = newp -> x25_udata + 4;
45341595Ssklower 	while (*ocp && ocp < (caddr_t)oldp -> xaddr_userdata + 12) {
45448753Ssklower 		if (newp -> x25_udlen == 0)
45548753Ssklower 			newp -> x25_udlen = 4;
45641595Ssklower 		*ncp++ = *ocp++;
45741595Ssklower 		newp -> x25_udlen++;
45841595Ssklower 	}
45941595Ssklower 	bcopy ((caddr_t)newp, mtod (m, char *), sizeof (*newp));
46045895Ssklower 	m -> m_len = sizeof (*newp);
46141595Ssklower }
46241595Ssklower 
46341595Ssklower /*
46441595Ssklower  * Do an in-place conversion of a new style
46541595Ssklower  * socket address to the old style
46641595Ssklower  */
46741595Ssklower 
46841595Ssklower static
46941595Ssklower new_to_old (m)
47041595Ssklower register struct mbuf *m;
47141595Ssklower {
47241595Ssklower 	register struct x25_sockaddr *oldp;
47341595Ssklower 	register struct sockaddr_x25 *newp;
47441595Ssklower 	register char *ocp, *ncp;
47541595Ssklower 	struct x25_sockaddr old;
47641595Ssklower 
47741595Ssklower 	oldp = &old;
47841595Ssklower 	newp = mtod (m, struct sockaddr_x25 *);
47941595Ssklower 	bzero ((caddr_t)oldp, sizeof (*oldp));
48041595Ssklower 
48141595Ssklower 	oldp -> xaddr_facilities = newp -> x25_opts.op_flags & X25_REVERSE_CHARGE;
48241595Ssklower 	if (newp -> x25_opts.op_psize == X25_PS128)
48341595Ssklower 		oldp -> xaddr_facilities |= XS_HIPRIO;	/* Datapac specific */
48441595Ssklower 	ocp = (char *)oldp -> xaddr_addr;
48541595Ssklower 	ncp = newp -> x25_addr;
48641595Ssklower 	while (*ncp) {
48741595Ssklower 		*ocp++ = *ncp++;
48841595Ssklower 		oldp -> xaddr_len++;
48941595Ssklower 	}
49041595Ssklower 
49141595Ssklower 	bcopy (newp -> x25_udata, (caddr_t)oldp -> xaddr_proto, 4);
49248753Ssklower 	if (newp -> x25_udlen > 4)
49348753Ssklower 		bcopy (newp -> x25_udata + 4, (caddr_t)oldp -> xaddr_userdata,
49448753Ssklower 			(unsigned)(newp -> x25_udlen - 4));
49541595Ssklower 
49641595Ssklower 	bcopy ((caddr_t)oldp, mtod (m, char *), sizeof (*oldp));
49741595Ssklower 	m -> m_len = sizeof (*oldp);
49841595Ssklower }
49941595Ssklower 
50045895Ssklower 
50145895Ssklower pk_checksockaddr (m)
50245895Ssklower struct mbuf *m;
50345895Ssklower {
50445895Ssklower 	register struct sockaddr_x25 *sa = mtod (m, struct sockaddr_x25 *);
50545895Ssklower 	register char *cp;
50645895Ssklower 
50745895Ssklower 	if (m -> m_len != sizeof (struct sockaddr_x25))
50845895Ssklower 		return (1);
50945895Ssklower 	if (sa -> x25_family != AF_CCITT ||
51045895Ssklower 		sa -> x25_udlen > sizeof (sa -> x25_udata))
51145895Ssklower 		return (1);
51245895Ssklower 	for (cp = sa -> x25_addr; *cp; cp++) {
51345895Ssklower 		if (*cp < '0' || *cp > '9' ||
51445895Ssklower 			cp >= &sa -> x25_addr[sizeof (sa -> x25_addr) - 1])
51545895Ssklower 			return (1);
51645895Ssklower 	}
51745895Ssklower 	return (0);
51845895Ssklower }
519*49027Ssklower 
52041595Ssklower pk_send (lcp, m)
52145297Ssklower struct pklcd *lcp;
52241595Ssklower register struct mbuf *m;
52341595Ssklower {
52445895Ssklower 	int mqbit = 0, error = 0;
52545895Ssklower 	register struct x25_packet *xp;
526*49027Ssklower 	register struct socket *so;
52741595Ssklower 
52845895Ssklower 	if (m -> m_type == MT_OOBDATA) {
52945895Ssklower 		if (lcp -> lcd_intrconf_pending)
53045895Ssklower 			error = ETOOMANYREFS;
53145895Ssklower 		if (m -> m_pkthdr.len > 32)
53245895Ssklower 			error = EMSGSIZE;
53345895Ssklower 		M_PREPEND(m, PKHEADERLN, M_WAITOK);
53445895Ssklower 		if (m == 0 || error)
53545895Ssklower 			goto bad;
53645895Ssklower 		*(mtod (m, octet *)) = 0;
53745895Ssklower 		xp = mtod (m, struct x25_packet *);
53845895Ssklower 		xp -> fmt_identifier = 1;
53945895Ssklower 		xp -> packet_type = X25_INTERRUPT;
54045895Ssklower 		SET_LCN(xp, lcp -> lcd_lcn);
541*49027Ssklower 		sbinsertoob ( (so = lcp -> lcd_so) ?
542*49027Ssklower 			&so -> so_snd : &lcp -> lcd_sb, m);
543*49027Ssklower 		goto send;
54445895Ssklower 	}
54541595Ssklower 	/*
54641595Ssklower 	 * Application has elected (at call setup time) to prepend
54741595Ssklower 	 * a control byte to each packet written indicating m-bit
54841595Ssklower 	 * and q-bit status.  Examine and then discard this byte.
54941595Ssklower 	 */
55041595Ssklower 	if (lcp -> lcd_flags & X25_MQBIT) {
55141595Ssklower 		if (m -> m_len < 1) {
55245297Ssklower 			m_freem (m);
55341595Ssklower 			return (EMSGSIZE);
55441595Ssklower 		}
55545895Ssklower 		mqbit = *(mtod (m, u_char *));
55641595Ssklower 		m -> m_len--;
55741936Ssklower 		m -> m_data++;
55845297Ssklower 		m -> m_pkthdr.len--;
55941595Ssklower 	}
560*49027Ssklower 	error = pk_fragment (lcp, m, mqbit & 0x80, mqbit & 0x40, 1);
561*49027Ssklower send:
562*49027Ssklower 	if (error == 0 && lcp -> lcd_state == DATA_TRANSFER)
563*49027Ssklower 		lcp -> lcd_send (lcp); /* XXXXXXXXX fix pk_output!!! */
56445297Ssklower 	return (error);
56545895Ssklower bad:
56645895Ssklower 	if (m)
56745895Ssklower 		m_freem (m);
56845895Ssklower 	return (error);
56941595Ssklower }
570