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*49933Ssklower * @(#)pk_usrreq.c 7.14 (Berkeley) 05/29/91 1341709Ssklower */ 1441595Ssklower 1542140Ssklower #include "param.h" 1642140Ssklower #include "systm.h" 1742140Ssklower #include "mbuf.h" 1842140Ssklower #include "socket.h" 19*49933Ssklower #include "socketvar.h" 2042140Ssklower #include "protosw.h" 2142140Ssklower #include "errno.h" 2241595Ssklower #include "ioctl.h" 2341595Ssklower #include "user.h" 2441595Ssklower #include "stat.h" 2541595Ssklower 2642140Ssklower #include "../net/if.h" 27*49933Ssklower #include "../net/route.h" 2841595Ssklower 2942140Ssklower #include "x25.h" 3042140Ssklower #include "pk.h" 3142140Ssklower #include "pk_var.h" 3242140Ssklower 3341595Ssklower /* 3441595Ssklower * 3541595Ssklower * X.25 Packet level protocol interface to socket abstraction. 3641595Ssklower * 3741595Ssklower * Process an X.25 user request on a logical channel. If this is a send 3841595Ssklower * request then m is the mbuf chain of the send data. If this is a timer 3941595Ssklower * expiration (called from the software clock routine) them timertype is 4041595Ssklower * the particular timer. 4141595Ssklower * 4241595Ssklower */ 4341595Ssklower 4441936Ssklower pk_usrreq (so, req, m, nam, control) 4541595Ssklower struct socket *so; 4641595Ssklower int req; 4741595Ssklower register struct mbuf *m, *nam; 4841936Ssklower struct mbuf *control; 4941595Ssklower { 5041595Ssklower register struct pklcd *lcp = (struct pklcd *) so -> so_pcb; 5141936Ssklower register int error = 0; 5241595Ssklower 5341936Ssklower if (req == PRU_CONTROL) 5447261Ssklower return (pk_control (so, (int)m, (caddr_t)nam, 5541936Ssklower (struct ifnet *)control)); 5645895Ssklower if (control && control -> m_len) { 5741936Ssklower error = EINVAL; 5841936Ssklower goto release; 5941595Ssklower } 6041936Ssklower if (lcp == NULL && req != PRU_ATTACH) { 6141936Ssklower error = EINVAL; 6241936Ssklower goto release; 6341595Ssklower } 6441595Ssklower 6541595Ssklower /* 6641595Ssklower pk_trace (pkcbhead, TR_USER, (struct pklcd *)0, 6741595Ssklower req, (struct x25_packet *)0); 6841595Ssklower */ 6941595Ssklower 7041595Ssklower switch (req) { 7141595Ssklower /* 7241595Ssklower * X.25 attaches to socket via PRU_ATTACH and allocates a logical 7341595Ssklower * channel descriptor. If the socket is to receive connections, 7441595Ssklower * then the LISTEN state is entered. 7541595Ssklower */ 7641595Ssklower case PRU_ATTACH: 7741595Ssklower if (lcp) { 7841595Ssklower error = EISCONN; 7941595Ssklower /* Socket already connected. */ 8041595Ssklower break; 8141595Ssklower } 8245165Ssklower lcp = pk_attach (so); 8345165Ssklower if (lcp == 0) 8445165Ssklower error = ENOBUFS; 8541595Ssklower break; 8641595Ssklower 8741595Ssklower /* 8841595Ssklower * Detach a logical channel from the socket. If the state of the 8941595Ssklower * channel is embryonic, simply discard it. Otherwise we have to 9041595Ssklower * initiate a PRU_DISCONNECT which will finish later. 9141595Ssklower */ 9241595Ssklower case PRU_DETACH: 9341595Ssklower pk_disconnect (lcp); 9441595Ssklower break; 9541595Ssklower 9641595Ssklower /* 9741595Ssklower * Give the socket an address. 9841595Ssklower */ 9941595Ssklower case PRU_BIND: 10041595Ssklower if (nam -> m_len == sizeof (struct x25_sockaddr)) 10141595Ssklower old_to_new (nam); 10241595Ssklower error = pk_bind (lcp, nam); 10341595Ssklower break; 10441595Ssklower 10541595Ssklower /* 10641595Ssklower * Prepare to accept connections. 10741595Ssklower */ 10841595Ssklower case PRU_LISTEN: 10945895Ssklower error = pk_listen (lcp); 11041595Ssklower break; 11141595Ssklower 11241595Ssklower /* 11341595Ssklower * Initiate a CALL REQUEST to peer entity. Enter state SENT_CALL 11441595Ssklower * and mark the socket as connecting. Set timer waiting for 11541595Ssklower * CALL ACCEPT or CLEAR. 11641595Ssklower */ 11741595Ssklower case PRU_CONNECT: 11841595Ssklower if (nam -> m_len == sizeof (struct x25_sockaddr)) 11941595Ssklower old_to_new (nam); 12045895Ssklower if (pk_checksockaddr (nam)) 12145895Ssklower return (EINVAL); 12245895Ssklower error = pk_connect (lcp, mtod (nam, struct sockaddr_x25 *)); 12341595Ssklower break; 12441595Ssklower 12541595Ssklower /* 12641595Ssklower * Initiate a disconnect to peer entity via a CLEAR REQUEST packet. 12741595Ssklower * The socket will be disconnected when we receive a confirmation 12841595Ssklower * or a clear collision. 12941595Ssklower */ 13041595Ssklower case PRU_DISCONNECT: 13141595Ssklower pk_disconnect (lcp); 13241595Ssklower break; 13341595Ssklower 13441595Ssklower /* 13541595Ssklower * Accept an INCOMING CALL. Most of the work has already been done 13641595Ssklower * by pk_input. Just return the callers address to the user. 13741595Ssklower */ 13841595Ssklower case PRU_ACCEPT: 13941595Ssklower if (lcp -> lcd_craddr == NULL) 14041595Ssklower break; 14141595Ssklower bcopy ((caddr_t)lcp -> lcd_craddr, mtod (nam, caddr_t), 14241595Ssklower sizeof (struct sockaddr_x25)); 14341595Ssklower nam -> m_len = sizeof (struct sockaddr_x25); 14441595Ssklower if (lcp -> lcd_flags & X25_OLDSOCKADDR) 14541595Ssklower new_to_old (nam); 14641595Ssklower break; 14741595Ssklower 14841595Ssklower /* 14941595Ssklower * After a receive, we should send a RR. 15041595Ssklower */ 15141595Ssklower case PRU_RCVD: 152*49933Ssklower pk_flowcontrol (lcp, /*sbspace (&so -> so_rcv) <= */ 0, 1); 15341595Ssklower break; 15441595Ssklower 15541595Ssklower /* 15645895Ssklower * Send INTERRUPT packet. 15745895Ssklower */ 15845895Ssklower case PRU_SENDOOB: 15945895Ssklower if (m == 0) { 16045895Ssklower MGETHDR(m, M_WAITOK, MT_OOBDATA); 16145895Ssklower m -> m_pkthdr.len = m -> m_len = 1; 16247261Ssklower *mtod (m, octet *) = 0; 16345895Ssklower } 16445895Ssklower if (m -> m_pkthdr.len > 32) { 16547261Ssklower m_freem (m); 16645895Ssklower error = EMSGSIZE; 16745895Ssklower break; 16845895Ssklower } 16945895Ssklower MCHTYPE(m, MT_OOBDATA); 17045895Ssklower /* FALLTHROUGH */ 17145895Ssklower 17245895Ssklower /* 17341595Ssklower * Do send by placing data on the socket output queue. 17441595Ssklower */ 17541595Ssklower case PRU_SEND: 17645895Ssklower if (control) { 17747261Ssklower register struct cmsghdr *ch = mtod (m, struct cmsghdr *); 17845895Ssklower control -> m_len -= sizeof (*ch); 17945895Ssklower control -> m_data += sizeof (*ch); 180*49933Ssklower error = pk_ctloutput (PRCO_SETOPT, so, ch -> cmsg_level, 18145895Ssklower ch -> cmsg_type, &control); 18245895Ssklower } 183*49933Ssklower if (error == 0 && m) 18445895Ssklower error = pk_send (lcp, m); 18541595Ssklower break; 18641595Ssklower 18741595Ssklower /* 18841595Ssklower * Abort a virtual circuit. For example all completed calls 18941595Ssklower * waiting acceptance. 19041595Ssklower */ 19141595Ssklower case PRU_ABORT: 19241595Ssklower pk_disconnect (lcp); 19341595Ssklower break; 19441595Ssklower 19541595Ssklower /* Begin unimplemented hooks. */ 19641595Ssklower 19741595Ssklower case PRU_SHUTDOWN: 19841595Ssklower error = EOPNOTSUPP; 19941595Ssklower break; 20041595Ssklower 20141595Ssklower case PRU_CONTROL: 20241595Ssklower error = EOPNOTSUPP; 20341595Ssklower break; 20441595Ssklower 20541595Ssklower case PRU_SENSE: 20641595Ssklower #ifdef BSD4_3 20741595Ssklower ((struct stat *)m) -> st_blksize = so -> so_snd.sb_hiwat; 20841595Ssklower #else 20941595Ssklower error = EOPNOTSUPP; 21041595Ssklower #endif 21141595Ssklower break; 21241595Ssklower 21341595Ssklower /* End unimplemented hooks. */ 21441595Ssklower 21541595Ssklower case PRU_SOCKADDR: 21641595Ssklower if (lcp -> lcd_ceaddr == 0) 21741595Ssklower return (EADDRNOTAVAIL); 21841595Ssklower nam -> m_len = sizeof (struct sockaddr_x25); 21941595Ssklower bcopy ((caddr_t)lcp -> lcd_ceaddr, mtod (nam, caddr_t), 22041595Ssklower sizeof (struct sockaddr_x25)); 22141595Ssklower if (lcp -> lcd_flags & X25_OLDSOCKADDR) 22241595Ssklower new_to_old (nam); 22341595Ssklower break; 22441595Ssklower 22541595Ssklower case PRU_PEERADDR: 22641595Ssklower if (lcp -> lcd_state != DATA_TRANSFER) 22741595Ssklower return (ENOTCONN); 22841595Ssklower nam -> m_len = sizeof (struct sockaddr_x25); 22941595Ssklower bcopy (lcp -> lcd_craddr ? (caddr_t)lcp -> lcd_craddr : 23041595Ssklower (caddr_t)lcp -> lcd_ceaddr, 23141595Ssklower mtod (nam, caddr_t), sizeof (struct sockaddr_x25)); 23241595Ssklower if (lcp -> lcd_flags & X25_OLDSOCKADDR) 23341595Ssklower new_to_old (nam); 23441595Ssklower break; 23541595Ssklower 23641595Ssklower /* 23741595Ssklower * Receive INTERRUPT packet. 23841595Ssklower */ 23941595Ssklower case PRU_RCVOOB: 24045895Ssklower if (so -> so_options & SO_OOBINLINE) { 24145895Ssklower register struct mbuf *n = so -> so_rcv.sb_mb; 24245895Ssklower if (n && n -> m_type == MT_OOBDATA) { 24345895Ssklower unsigned len = n -> m_pkthdr.len; 24445895Ssklower so -> so_rcv.sb_mb = n -> m_nextpkt; 24545895Ssklower if (len != n -> m_len && 24647261Ssklower (n = m_pullup (n, len)) == 0) 24745895Ssklower break; 24845895Ssklower m -> m_len = len; 24947261Ssklower bcopy (mtod (m, caddr_t), mtod (n, caddr_t), len); 25047261Ssklower m_freem (n); 25145895Ssklower } 25245895Ssklower break; 25345895Ssklower } 25441595Ssklower m -> m_len = 1; 25541595Ssklower *mtod (m, char *) = lcp -> lcd_intrdata; 25641595Ssklower break; 25741595Ssklower 25841595Ssklower default: 25941595Ssklower panic ("pk_usrreq"); 26041595Ssklower } 26141936Ssklower release: 26241936Ssklower if (control != NULL) 26347261Ssklower m_freem (control); 26441595Ssklower return (error); 26541595Ssklower } 26641595Ssklower 26742277Ssklower /* 26842277Ssklower * If you want to use UBC X.25 level 3 in conjunction with some 26945895Ssklower * other X.25 level 2 driver, have the ifp -> if_ioctl routine 270*49933Ssklower * assign pk_start to ia -> ia_start when called with SIOCSIFCONF_X25. 27142277Ssklower */ 27242277Ssklower /* ARGSUSED */ 27342277Ssklower pk_start (lcp) 27442277Ssklower register struct pklcd *lcp; 27542277Ssklower { 27649027Ssklower pk_output (lcp); 27749027Ssklower return (0); /* XXX pk_output should return a value */ 27842277Ssklower } 27942277Ssklower 280*49933Ssklower #ifndef _offsetof 281*49933Ssklower #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) 282*49933Ssklower #endif 283*49933Ssklower struct sockaddr_x25 pk_sockmask = { 284*49933Ssklower _offsetof(struct sockaddr_x25, x25_addr[0]), 285*49933Ssklower 0, -1}; 286*49933Ssklower 28741595Ssklower /*ARGSUSED*/ 28841595Ssklower pk_control (so, cmd, data, ifp) 28941595Ssklower struct socket *so; 29041595Ssklower int cmd; 29141595Ssklower caddr_t data; 29241595Ssklower register struct ifnet *ifp; 29341595Ssklower { 29442140Ssklower register struct ifreq_x25 *ifr = (struct ifreq_x25 *)data; 29541595Ssklower register struct ifaddr *ifa = 0; 29641936Ssklower register struct x25_ifaddr *ia = 0; 29742277Ssklower struct pklcd *dev_lcp = 0; 29845297Ssklower int error, s, old_maxlcn; 29941936Ssklower unsigned n; 30041595Ssklower 30141595Ssklower /* 30241595Ssklower * Find address for this interface, if it exists. 30341595Ssklower */ 30441595Ssklower if (ifp) 30545895Ssklower for (ifa = ifp -> if_addrlist; ifa; ifa = ifa -> ifa_next) 30645895Ssklower if (ifa -> ifa_addr -> sa_family == AF_CCITT) 30741595Ssklower break; 30841595Ssklower 30941936Ssklower ia = (struct x25_ifaddr *)ifa; 31041595Ssklower switch (cmd) { 31142140Ssklower case SIOCGIFCONF_X25: 31241595Ssklower if (ifa == 0) 31341595Ssklower return (EADDRNOTAVAIL); 31445895Ssklower ifr -> ifr_xc = ia -> ia_xc; 31541595Ssklower return (0); 31641595Ssklower 31742140Ssklower case SIOCSIFCONF_X25: 31847261Ssklower if (error = suser (u.u_cred, &u.u_acflag)) 31945165Ssklower return (error); 32041595Ssklower if (ifp == 0) 32147261Ssklower panic ("pk_control"); 32241595Ssklower if (ifa == (struct ifaddr *)0) { 32341595Ssklower register struct mbuf *m; 32441595Ssklower 32542277Ssklower MALLOC(ia, struct x25_ifaddr *, sizeof (*ia), 32642277Ssklower M_IFADDR, M_WAITOK); 32742277Ssklower if (ia == 0) 32841595Ssklower return (ENOBUFS); 32947261Ssklower bzero ((caddr_t)ia, sizeof (*ia)); 33045895Ssklower if (ifa = ifp -> if_addrlist) { 33145895Ssklower for ( ; ifa -> ifa_next; ifa = ifa -> ifa_next) 33241595Ssklower ; 33345895Ssklower ifa -> ifa_next = &ia -> ia_ifa; 33441595Ssklower } else 33545895Ssklower ifp -> if_addrlist = &ia -> ia_ifa; 33645895Ssklower ifa = &ia -> ia_ifa; 337*49933Ssklower ifa -> ifa_netmask = (struct sockaddr *)&pk_sockmask; 33845895Ssklower ifa -> ifa_addr = (struct sockaddr *)&ia -> ia_xc.xc_addr; 339*49933Ssklower ifa -> ifa_dstaddr = (struct sockaddr *)&ia -> ia_dstaddr; /* XXX */ 34045895Ssklower ia -> ia_ifp = ifp; 341*49933Ssklower ia -> ia_dstaddr.x25_family = AF_CCITT; 342*49933Ssklower ia -> ia_dstaddr.x25_len = pk_sockmask.x25_len; 343*49933Ssklower } else { 344*49933Ssklower rtinit (ifa, (int)RTM_DELETE, 0); 34541595Ssklower } 34645895Ssklower old_maxlcn = ia -> ia_maxlcn; 34745895Ssklower ia -> ia_xc = ifr -> ifr_xc; 348*49933Ssklower ia -> ia_dstaddr.x25_net = ia -> ia_xc.xc_addr.x25_net; 349*49933Ssklower if (ia -> ia_maxlcn != old_maxlcn && old_maxlcn != 0) { 350*49933Ssklower /* VERY messy XXX */ 351*49933Ssklower register struct pkcb *pkp; 352*49933Ssklower for (pkp = pkcbhead; pkp; pkp = pkp -> pk_next) 353*49933Ssklower if (pkp -> pk_ia == ia) 354*49933Ssklower pk_resize (pkp); 35541936Ssklower } 35641595Ssklower /* 35741595Ssklower * Give the interface a chance to initialize if this 35841595Ssklower * is its first address, and to validate the address. 35941595Ssklower */ 360*49933Ssklower ia -> ia_start = pk_start; 36141936Ssklower s = splimp(); 36245895Ssklower if (ifp -> if_ioctl) 36345895Ssklower error = (*ifp -> if_ioctl)(ifp, SIOCSIFCONF_X25, ifa); 36445297Ssklower if (error) 36545895Ssklower ifp -> if_flags &= ~IFF_UP; 366*49933Ssklower else 367*49933Ssklower error = rtinit (ifa, (int)RTM_ADD, RTF_UP); 36845895Ssklower splx (s); 36941936Ssklower return (error); 37041595Ssklower 37141595Ssklower default: 37245895Ssklower if (ifp == 0 || ifp -> if_ioctl == 0) 37341595Ssklower return (EOPNOTSUPP); 37445895Ssklower return ((*ifp -> if_ioctl)(ifp, cmd, data)); 37541595Ssklower } 37641595Ssklower } 37741595Ssklower 37847261Ssklower pk_ctloutput (cmd, so, level, optname, mp) 37945165Ssklower struct socket *so; 38045165Ssklower struct mbuf **mp; 38145165Ssklower int cmd, level, optname; 38245165Ssklower { 38345165Ssklower register struct mbuf *m = *mp; 38445895Ssklower register struct pklcd *lcp = (struct pklcd *) so -> so_pcb; 385*49933Ssklower int error = EOPNOTSUPP; 38645165Ssklower 387*49933Ssklower if (m == 0) 388*49933Ssklower return (EINVAL); 38945165Ssklower if (cmd == PRCO_SETOPT) switch (optname) { 390*49933Ssklower case PK_FACILITIES: 39145165Ssklower if (m == 0) 39245165Ssklower return (EINVAL); 393*49933Ssklower lcp -> lcd_facilities = m; 394*49933Ssklower *mp = 0; 395*49933Ssklower return (0); 396*49933Ssklower 397*49933Ssklower case PK_ACCTFILE: 39845895Ssklower if (m -> m_len) 39947261Ssklower error = pk_accton (mtod (m, char *)); 40045165Ssklower else 40145895Ssklower error = pk_accton ((char *)0); 402*49933Ssklower break; 40345895Ssklower 404*49933Ssklower case PK_RTATTACH: 405*49933Ssklower error = pk_rtattach (so, m); 406*49933Ssklower break; 407*49933Ssklower 408*49933Ssklower case PK_PRLISTEN: 409*49933Ssklower error = pk_user_protolisten (mtod (m, u_char *)); 41045165Ssklower } 41145165Ssklower if (*mp) { 41245895Ssklower (void) m_freem (*mp); 41345165Ssklower *mp = 0; 41445165Ssklower } 41545165Ssklower return (EOPNOTSUPP); 41645165Ssklower 41745165Ssklower } 41845165Ssklower 419*49933Ssklower 42041595Ssklower /* 42141595Ssklower * Do an in-place conversion of an "old style" 42241595Ssklower * socket address to the new style 42341595Ssklower */ 42441595Ssklower 42541595Ssklower static 42641595Ssklower old_to_new (m) 42741595Ssklower register struct mbuf *m; 42841595Ssklower { 42941595Ssklower register struct x25_sockaddr *oldp; 43041595Ssklower register struct sockaddr_x25 *newp; 43141595Ssklower register char *ocp, *ncp; 43241595Ssklower struct sockaddr_x25 new; 43341595Ssklower 43441595Ssklower oldp = mtod (m, struct x25_sockaddr *); 43541595Ssklower newp = &new; 43641595Ssklower bzero ((caddr_t)newp, sizeof (*newp)); 43741595Ssklower 43841595Ssklower newp -> x25_family = AF_CCITT; 43948753Ssklower newp -> x25_len = sizeof(*newp); 44045895Ssklower newp -> x25_opts.op_flags = (oldp -> xaddr_facilities & X25_REVERSE_CHARGE) 44141595Ssklower | X25_MQBIT | X25_OLDSOCKADDR; 44241595Ssklower if (oldp -> xaddr_facilities & XS_HIPRIO) /* Datapac specific */ 44341595Ssklower newp -> x25_opts.op_psize = X25_PS128; 44441595Ssklower bcopy ((caddr_t)oldp -> xaddr_addr, newp -> x25_addr, 44548753Ssklower (unsigned)min (oldp -> xaddr_len, sizeof (newp -> x25_addr) - 1)); 44648753Ssklower if (bcmp ((caddr_t)oldp -> xaddr_proto, newp -> x25_udata, 4) != 0) { 44748753Ssklower bcopy ((caddr_t)oldp -> xaddr_proto, newp -> x25_udata, 4); 44848753Ssklower newp -> x25_udlen = 4; 44948753Ssklower } 45041595Ssklower ocp = (caddr_t)oldp -> xaddr_userdata; 45141595Ssklower ncp = newp -> x25_udata + 4; 45241595Ssklower while (*ocp && ocp < (caddr_t)oldp -> xaddr_userdata + 12) { 45348753Ssklower if (newp -> x25_udlen == 0) 45448753Ssklower newp -> x25_udlen = 4; 45541595Ssklower *ncp++ = *ocp++; 45641595Ssklower newp -> x25_udlen++; 45741595Ssklower } 45841595Ssklower bcopy ((caddr_t)newp, mtod (m, char *), sizeof (*newp)); 45945895Ssklower m -> m_len = sizeof (*newp); 46041595Ssklower } 46141595Ssklower 46241595Ssklower /* 46341595Ssklower * Do an in-place conversion of a new style 46441595Ssklower * socket address to the old style 46541595Ssklower */ 46641595Ssklower 46741595Ssklower static 46841595Ssklower new_to_old (m) 46941595Ssklower register struct mbuf *m; 47041595Ssklower { 47141595Ssklower register struct x25_sockaddr *oldp; 47241595Ssklower register struct sockaddr_x25 *newp; 47341595Ssklower register char *ocp, *ncp; 47441595Ssklower struct x25_sockaddr old; 47541595Ssklower 47641595Ssklower oldp = &old; 47741595Ssklower newp = mtod (m, struct sockaddr_x25 *); 47841595Ssklower bzero ((caddr_t)oldp, sizeof (*oldp)); 47941595Ssklower 48041595Ssklower oldp -> xaddr_facilities = newp -> x25_opts.op_flags & X25_REVERSE_CHARGE; 48141595Ssklower if (newp -> x25_opts.op_psize == X25_PS128) 48241595Ssklower oldp -> xaddr_facilities |= XS_HIPRIO; /* Datapac specific */ 48341595Ssklower ocp = (char *)oldp -> xaddr_addr; 48441595Ssklower ncp = newp -> x25_addr; 48541595Ssklower while (*ncp) { 48641595Ssklower *ocp++ = *ncp++; 48741595Ssklower oldp -> xaddr_len++; 48841595Ssklower } 48941595Ssklower 49041595Ssklower bcopy (newp -> x25_udata, (caddr_t)oldp -> xaddr_proto, 4); 49148753Ssklower if (newp -> x25_udlen > 4) 49248753Ssklower bcopy (newp -> x25_udata + 4, (caddr_t)oldp -> xaddr_userdata, 49348753Ssklower (unsigned)(newp -> x25_udlen - 4)); 49441595Ssklower 49541595Ssklower bcopy ((caddr_t)oldp, mtod (m, char *), sizeof (*oldp)); 49641595Ssklower m -> m_len = sizeof (*oldp); 49741595Ssklower } 49841595Ssklower 49945895Ssklower 50045895Ssklower pk_checksockaddr (m) 50145895Ssklower struct mbuf *m; 50245895Ssklower { 50345895Ssklower register struct sockaddr_x25 *sa = mtod (m, struct sockaddr_x25 *); 50445895Ssklower register char *cp; 50545895Ssklower 50645895Ssklower if (m -> m_len != sizeof (struct sockaddr_x25)) 50745895Ssklower return (1); 50845895Ssklower if (sa -> x25_family != AF_CCITT || 50945895Ssklower sa -> x25_udlen > sizeof (sa -> x25_udata)) 51045895Ssklower return (1); 51145895Ssklower for (cp = sa -> x25_addr; *cp; cp++) { 51245895Ssklower if (*cp < '0' || *cp > '9' || 51345895Ssklower cp >= &sa -> x25_addr[sizeof (sa -> x25_addr) - 1]) 51445895Ssklower return (1); 51545895Ssklower } 51645895Ssklower return (0); 51745895Ssklower } 51849027Ssklower 51941595Ssklower pk_send (lcp, m) 52045297Ssklower struct pklcd *lcp; 52141595Ssklower register struct mbuf *m; 52241595Ssklower { 52345895Ssklower int mqbit = 0, error = 0; 52445895Ssklower register struct x25_packet *xp; 52549027Ssklower register struct socket *so; 52641595Ssklower 52745895Ssklower if (m -> m_type == MT_OOBDATA) { 52845895Ssklower if (lcp -> lcd_intrconf_pending) 52945895Ssklower error = ETOOMANYREFS; 53045895Ssklower if (m -> m_pkthdr.len > 32) 53145895Ssklower error = EMSGSIZE; 53245895Ssklower M_PREPEND(m, PKHEADERLN, M_WAITOK); 53345895Ssklower if (m == 0 || error) 53445895Ssklower goto bad; 53545895Ssklower *(mtod (m, octet *)) = 0; 53645895Ssklower xp = mtod (m, struct x25_packet *); 53745895Ssklower xp -> fmt_identifier = 1; 53845895Ssklower xp -> packet_type = X25_INTERRUPT; 53945895Ssklower SET_LCN(xp, lcp -> lcd_lcn); 54049027Ssklower sbinsertoob ( (so = lcp -> lcd_so) ? 54149027Ssklower &so -> so_snd : &lcp -> lcd_sb, m); 54249027Ssklower goto send; 54345895Ssklower } 54441595Ssklower /* 54541595Ssklower * Application has elected (at call setup time) to prepend 54641595Ssklower * a control byte to each packet written indicating m-bit 54741595Ssklower * and q-bit status. Examine and then discard this byte. 54841595Ssklower */ 54941595Ssklower if (lcp -> lcd_flags & X25_MQBIT) { 55041595Ssklower if (m -> m_len < 1) { 55145297Ssklower m_freem (m); 55241595Ssklower return (EMSGSIZE); 55341595Ssklower } 55445895Ssklower mqbit = *(mtod (m, u_char *)); 55541595Ssklower m -> m_len--; 55641936Ssklower m -> m_data++; 55745297Ssklower m -> m_pkthdr.len--; 55841595Ssklower } 55949027Ssklower error = pk_fragment (lcp, m, mqbit & 0x80, mqbit & 0x40, 1); 56049027Ssklower send: 56149027Ssklower if (error == 0 && lcp -> lcd_state == DATA_TRANSFER) 56249027Ssklower lcp -> lcd_send (lcp); /* XXXXXXXXX fix pk_output!!! */ 56345297Ssklower return (error); 56445895Ssklower bad: 56545895Ssklower if (m) 56645895Ssklower m_freem (m); 56745895Ssklower return (error); 56841595Ssklower } 569