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