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