141709Ssklower /* 241709Ssklower * Copyright (c) University of British Columbia, 1984 357024Ssklower * Copyright (C) Computer Science Department IV, 457024Ssklower * University of Erlangen-Nuremberg, Germany, 1992 5*63216Sbostic * Copyright (c) 1991, 1992, 1993 6*63216Sbostic * 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*63216Sbostic * @(#)pk_usrreq.c 8.1 (Berkeley) 06/10/93 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 */ 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; 29741595Ssklower int 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 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 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