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*45895Ssklower * @(#)pk_usrreq.c 7.10 (Berkeley) 01/09/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) 5341936Ssklower return (pk_control(so, (int)m, (caddr_t)nam, 5441936Ssklower (struct ifnet *)control)); 55*45895Ssklower 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: 108*45895Ssklower 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); 119*45895Ssklower if (pk_checksockaddr (nam)) 120*45895Ssklower return (EINVAL); 121*45895Ssklower 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); 15441595Ssklower break; 15541595Ssklower 15641595Ssklower /* 157*45895Ssklower * Send INTERRUPT packet. 158*45895Ssklower */ 159*45895Ssklower case PRU_SENDOOB: 160*45895Ssklower if (m == 0) { 161*45895Ssklower MGETHDR(m, M_WAITOK, MT_OOBDATA); 162*45895Ssklower m -> m_pkthdr.len = m -> m_len = 1; 163*45895Ssklower *mtod(m, octet *) = 0; 164*45895Ssklower } 165*45895Ssklower if (m -> m_pkthdr.len > 32) { 166*45895Ssklower m_freem(m); 167*45895Ssklower error = EMSGSIZE; 168*45895Ssklower break; 169*45895Ssklower } 170*45895Ssklower MCHTYPE(m, MT_OOBDATA); 171*45895Ssklower /* FALLTHROUGH */ 172*45895Ssklower 173*45895Ssklower /* 17441595Ssklower * Do send by placing data on the socket output queue. 17541595Ssklower */ 17641595Ssklower case PRU_SEND: 177*45895Ssklower if (control) { 178*45895Ssklower register struct cmsghdr *ch = mtod(m, struct cmsghdr *); 179*45895Ssklower control -> m_len -= sizeof (*ch); 180*45895Ssklower control -> m_data += sizeof (*ch); 181*45895Ssklower pk_ctloutput(PRCO_SETOPT, so, ch -> cmsg_level, 182*45895Ssklower ch -> cmsg_type, &control); 183*45895Ssklower } 184*45895Ssklower if (m) 185*45895Ssklower error = pk_send (lcp, m); 18641595Ssklower break; 18741595Ssklower 18841595Ssklower /* 18941595Ssklower * Abort a virtual circuit. For example all completed calls 19041595Ssklower * waiting acceptance. 19141595Ssklower */ 19241595Ssklower case PRU_ABORT: 19341595Ssklower pk_disconnect (lcp); 19441595Ssklower break; 19541595Ssklower 19641595Ssklower /* Begin unimplemented hooks. */ 19741595Ssklower 19841595Ssklower case PRU_SHUTDOWN: 19941595Ssklower error = EOPNOTSUPP; 20041595Ssklower break; 20141595Ssklower 20241595Ssklower case PRU_CONTROL: 20341595Ssklower error = EOPNOTSUPP; 20441595Ssklower break; 20541595Ssklower 20641595Ssklower case PRU_SENSE: 20741595Ssklower #ifdef BSD4_3 20841595Ssklower ((struct stat *)m) -> st_blksize = so -> so_snd.sb_hiwat; 20941595Ssklower #else 21041595Ssklower error = EOPNOTSUPP; 21141595Ssklower #endif 21241595Ssklower break; 21341595Ssklower 21441595Ssklower /* End unimplemented hooks. */ 21541595Ssklower 21641595Ssklower case PRU_SOCKADDR: 21741595Ssklower if (lcp -> lcd_ceaddr == 0) 21841595Ssklower return (EADDRNOTAVAIL); 21941595Ssklower nam -> m_len = sizeof (struct sockaddr_x25); 22041595Ssklower bcopy ((caddr_t)lcp -> lcd_ceaddr, mtod (nam, caddr_t), 22141595Ssklower sizeof (struct sockaddr_x25)); 22241595Ssklower if (lcp -> lcd_flags & X25_OLDSOCKADDR) 22341595Ssklower new_to_old (nam); 22441595Ssklower break; 22541595Ssklower 22641595Ssklower case PRU_PEERADDR: 22741595Ssklower if (lcp -> lcd_state != DATA_TRANSFER) 22841595Ssklower return (ENOTCONN); 22941595Ssklower nam -> m_len = sizeof (struct sockaddr_x25); 23041595Ssklower bcopy (lcp -> lcd_craddr ? (caddr_t)lcp -> lcd_craddr : 23141595Ssklower (caddr_t)lcp -> lcd_ceaddr, 23241595Ssklower mtod (nam, caddr_t), sizeof (struct sockaddr_x25)); 23341595Ssklower if (lcp -> lcd_flags & X25_OLDSOCKADDR) 23441595Ssklower new_to_old (nam); 23541595Ssklower break; 23641595Ssklower 23741595Ssklower /* 23841595Ssklower * Receive INTERRUPT packet. 23941595Ssklower */ 24041595Ssklower case PRU_RCVOOB: 241*45895Ssklower if (so -> so_options & SO_OOBINLINE) { 242*45895Ssklower register struct mbuf *n = so -> so_rcv.sb_mb; 243*45895Ssklower if (n && n -> m_type == MT_OOBDATA) { 244*45895Ssklower unsigned len = n -> m_pkthdr.len; 245*45895Ssklower so -> so_rcv.sb_mb = n -> m_nextpkt; 246*45895Ssklower if (len != n -> m_len && 247*45895Ssklower (n = m_pullup(n, len)) == 0) 248*45895Ssklower break; 249*45895Ssklower m -> m_len = len; 250*45895Ssklower bcopy(mtod(m, caddr_t), mtod(n, caddr_t), len); 251*45895Ssklower m_freem(n); 252*45895Ssklower } 253*45895Ssklower break; 254*45895Ssklower } 25541595Ssklower m -> m_len = 1; 25641595Ssklower *mtod (m, char *) = lcp -> lcd_intrdata; 25741595Ssklower break; 25841595Ssklower 25941595Ssklower default: 26041595Ssklower panic ("pk_usrreq"); 26141595Ssklower } 26241936Ssklower release: 26341936Ssklower if (control != NULL) 26441936Ssklower m_freem(control); 26541595Ssklower return (error); 26641595Ssklower } 26741595Ssklower 26842277Ssklower /* 26942277Ssklower * If you want to use UBC X.25 level 3 in conjunction with some 270*45895Ssklower * other X.25 level 2 driver, have the ifp -> if_ioctl routine 27142277Ssklower * assign pk_start to pkp -> pk_start when called with SIOCSIFCONF_X25. 27242277Ssklower */ 27342277Ssklower /* ARGSUSED */ 27442277Ssklower pk_start (lcp) 27542277Ssklower register struct pklcd *lcp; 27642277Ssklower { 27742277Ssklower extern int pk_send(); 27842277Ssklower 27945165Ssklower lcp -> lcd_send = pk_send; 28042277Ssklower return (pk_output(lcp)); 28142277Ssklower } 28242277Ssklower 28341595Ssklower /*ARGSUSED*/ 28441595Ssklower pk_control (so, cmd, data, ifp) 28541595Ssklower struct socket *so; 28641595Ssklower int cmd; 28741595Ssklower caddr_t data; 28841595Ssklower register struct ifnet *ifp; 28941595Ssklower { 29042140Ssklower register struct ifreq_x25 *ifr = (struct ifreq_x25 *)data; 29141595Ssklower register struct ifaddr *ifa = 0; 29241936Ssklower register struct x25_ifaddr *ia = 0; 29342277Ssklower struct pklcd *dev_lcp = 0; 29445297Ssklower int error, s, old_maxlcn; 29541936Ssklower unsigned n; 29641595Ssklower 29741595Ssklower /* 29841595Ssklower * Find address for this interface, if it exists. 29941595Ssklower */ 30041595Ssklower if (ifp) 301*45895Ssklower for (ifa = ifp -> if_addrlist; ifa; ifa = ifa -> ifa_next) 302*45895Ssklower if (ifa -> ifa_addr -> sa_family == AF_CCITT) 30341595Ssklower break; 30441595Ssklower 30541936Ssklower ia = (struct x25_ifaddr *)ifa; 30641595Ssklower switch (cmd) { 30742140Ssklower case SIOCGIFCONF_X25: 30841595Ssklower if (ifa == 0) 30941595Ssklower return (EADDRNOTAVAIL); 310*45895Ssklower ifr -> ifr_xc = ia -> ia_xc; 31141595Ssklower return (0); 31241595Ssklower 31342140Ssklower case SIOCSIFCONF_X25: 31445165Ssklower if (error = suser(u.u_cred, &u.u_acflag)) 31545165Ssklower return (error); 31641595Ssklower if (ifp == 0) 31741595Ssklower panic("pk_control"); 31841595Ssklower if (ifa == (struct ifaddr *)0) { 31941595Ssklower register struct mbuf *m; 32041595Ssklower 32142277Ssklower MALLOC(ia, struct x25_ifaddr *, sizeof (*ia), 32242277Ssklower M_IFADDR, M_WAITOK); 32342277Ssklower if (ia == 0) 32441595Ssklower return (ENOBUFS); 32545297Ssklower bzero((caddr_t)ia, sizeof (*ia)); 326*45895Ssklower if (ifa = ifp -> if_addrlist) { 327*45895Ssklower for ( ; ifa -> ifa_next; ifa = ifa -> ifa_next) 32841595Ssklower ; 329*45895Ssklower ifa -> ifa_next = &ia -> ia_ifa; 33041595Ssklower } else 331*45895Ssklower ifp -> if_addrlist = &ia -> ia_ifa; 332*45895Ssklower ifa = &ia -> ia_ifa; 333*45895Ssklower ifa -> ifa_netmask = (struct sockaddr *)&ia -> ia_sockmask; 334*45895Ssklower ifa -> ifa_addr = (struct sockaddr *)&ia -> ia_xc.xc_addr; 335*45895Ssklower ia -> ia_xcp = &ia -> ia_xc; 336*45895Ssklower ia -> ia_ifp = ifp; 337*45895Ssklower ia -> ia_pkcb.pk_ia = ia; 338*45895Ssklower ia -> ia_pkcb.pk_next = pkcbhead; 339*45895Ssklower ia -> ia_pkcb.pk_state = DTE_WAITING; 340*45895Ssklower ia -> ia_pkcb.pk_start = pk_start; 341*45895Ssklower pkcbhead = &ia -> ia_pkcb; 34241595Ssklower } 343*45895Ssklower old_maxlcn = ia -> ia_maxlcn; 344*45895Ssklower ia -> ia_xc = ifr -> ifr_xc; 345*45895Ssklower if (ia -> ia_chan && (ia -> ia_maxlcn != old_maxlcn)) { 346*45895Ssklower pk_restart(&ia -> ia_pkcb, X25_RESTART_NETWORK_CONGESTION); 347*45895Ssklower dev_lcp = ia -> ia_chan[0]; 348*45895Ssklower free((caddr_t)ia -> ia_chan, M_IFADDR); 349*45895Ssklower ia -> ia_chan = 0; 35041936Ssklower } 351*45895Ssklower if (ia -> ia_chan == 0) { 352*45895Ssklower n = (ia -> ia_maxlcn + 1) * sizeof(struct pklcd *); 353*45895Ssklower ia -> ia_chan = (struct pklcd **) malloc(n, M_IFADDR, M_WAITOK); 354*45895Ssklower if (ia -> ia_chan) { 355*45895Ssklower bzero((caddr_t)ia -> ia_chan, n); 35642277Ssklower if (dev_lcp == 0) 35742277Ssklower dev_lcp = pk_attach((struct socket *)0); 358*45895Ssklower ia -> ia_chan[0] = dev_lcp; 359*45895Ssklower dev_lcp -> lcd_state = READY; 360*45895Ssklower dev_lcp -> lcd_pkp = &ia -> ia_pkcb; 36142277Ssklower } else { 36242277Ssklower if (dev_lcp) 36342277Ssklower pk_close(dev_lcp); 36442277Ssklower return (ENOBUFS); 36542277Ssklower } 36642140Ssklower } 36741595Ssklower /* 36841595Ssklower * Give the interface a chance to initialize if this 36941595Ssklower * is its first address, and to validate the address. 37041595Ssklower */ 37141936Ssklower s = splimp(); 372*45895Ssklower if (ifp -> if_ioctl) 373*45895Ssklower error = (*ifp -> if_ioctl)(ifp, SIOCSIFCONF_X25, ifa); 37445297Ssklower if (error) 375*45895Ssklower ifp -> if_flags &= ~IFF_UP; 376*45895Ssklower splx (s); 37741936Ssklower return (error); 37841595Ssklower 37941595Ssklower default: 380*45895Ssklower if (ifp == 0 || ifp -> if_ioctl == 0) 38141595Ssklower return (EOPNOTSUPP); 382*45895Ssklower return ((*ifp -> if_ioctl)(ifp, cmd, data)); 38341595Ssklower } 38441595Ssklower } 38541595Ssklower 38645165Ssklower 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; 392*45895Ssklower register struct pklcd *lcp = (struct pklcd *) so -> so_pcb; 39345165Ssklower int error; 39445165Ssklower 39545165Ssklower if (cmd == PRCO_SETOPT) switch (optname) { 39645165Ssklower case PK_ACCTFILE: 39745165Ssklower if (m == 0) 39845165Ssklower return (EINVAL); 399*45895Ssklower if (m -> m_len) 400*45895Ssklower error = pk_accton (mtod(m, char *)); 40145165Ssklower else 402*45895Ssklower error = pk_accton ((char *)0); 403*45895Ssklower (void) m_freem (m); 40445165Ssklower *mp = 0; 40545165Ssklower return (error); 406*45895Ssklower 407*45895Ssklower case PK_FACILITIES: 408*45895Ssklower if (m == 0) 409*45895Ssklower return (EINVAL); 410*45895Ssklower lcp -> lcd_facilities = m; 411*45895Ssklower *mp = 0; 412*45895Ssklower return (0); 41345165Ssklower } 41445165Ssklower if (*mp) { 415*45895Ssklower (void) m_freem (*mp); 41645165Ssklower *mp = 0; 41745165Ssklower } 41845165Ssklower return (EOPNOTSUPP); 41945165Ssklower 42045165Ssklower } 42145165Ssklower 42241595Ssklower /* 42341595Ssklower * Do an in-place conversion of an "old style" 42441595Ssklower * socket address to the new style 42541595Ssklower */ 42641595Ssklower 42741595Ssklower static 42841595Ssklower old_to_new (m) 42941595Ssklower register struct mbuf *m; 43041595Ssklower { 43141595Ssklower register struct x25_sockaddr *oldp; 43241595Ssklower register struct sockaddr_x25 *newp; 43341595Ssklower register char *ocp, *ncp; 43441595Ssklower struct sockaddr_x25 new; 43541595Ssklower 43641595Ssklower oldp = mtod (m, struct x25_sockaddr *); 43741595Ssklower newp = &new; 43841595Ssklower bzero ((caddr_t)newp, sizeof (*newp)); 43941595Ssklower 44041595Ssklower newp -> x25_family = AF_CCITT; 441*45895Ssklower 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, 44641595Ssklower (unsigned)min (oldp -> xaddr_len, sizeof (newp -> x25_addr) - 1)); 44741595Ssklower bcopy ((caddr_t)oldp -> xaddr_proto, newp -> x25_udata, 4); 44841595Ssklower newp -> x25_udlen = 4; 44941595Ssklower 45041595Ssklower ocp = (caddr_t)oldp -> xaddr_userdata; 45141595Ssklower ncp = newp -> x25_udata + 4; 45241595Ssklower while (*ocp && ocp < (caddr_t)oldp -> xaddr_userdata + 12) { 45341595Ssklower *ncp++ = *ocp++; 45441595Ssklower newp -> x25_udlen++; 45541595Ssklower } 45641595Ssklower 45741595Ssklower bcopy ((caddr_t)newp, mtod (m, char *), sizeof (*newp)); 458*45895Ssklower m -> m_len = sizeof (*newp); 45941595Ssklower } 46041595Ssklower 46141595Ssklower /* 46241595Ssklower * Do an in-place conversion of a new style 46341595Ssklower * socket address to the old style 46441595Ssklower */ 46541595Ssklower 46641595Ssklower static 46741595Ssklower new_to_old (m) 46841595Ssklower register struct mbuf *m; 46941595Ssklower { 47041595Ssklower register struct x25_sockaddr *oldp; 47141595Ssklower register struct sockaddr_x25 *newp; 47241595Ssklower register char *ocp, *ncp; 47341595Ssklower struct x25_sockaddr old; 47441595Ssklower 47541595Ssklower oldp = &old; 47641595Ssklower newp = mtod (m, struct sockaddr_x25 *); 47741595Ssklower bzero ((caddr_t)oldp, sizeof (*oldp)); 47841595Ssklower 47941595Ssklower oldp -> xaddr_facilities = newp -> x25_opts.op_flags & X25_REVERSE_CHARGE; 48041595Ssklower if (newp -> x25_opts.op_psize == X25_PS128) 48141595Ssklower oldp -> xaddr_facilities |= XS_HIPRIO; /* Datapac specific */ 48241595Ssklower ocp = (char *)oldp -> xaddr_addr; 48341595Ssklower ncp = newp -> x25_addr; 48441595Ssklower while (*ncp) { 48541595Ssklower *ocp++ = *ncp++; 48641595Ssklower oldp -> xaddr_len++; 48741595Ssklower } 48841595Ssklower 48941595Ssklower bcopy (newp -> x25_udata, (caddr_t)oldp -> xaddr_proto, 4); 49041595Ssklower bcopy (newp -> x25_udata + 4, (caddr_t)oldp -> xaddr_userdata, 49141595Ssklower (unsigned)(newp -> x25_udlen - 4)); 49241595Ssklower 49341595Ssklower bcopy ((caddr_t)oldp, mtod (m, char *), sizeof (*oldp)); 49441595Ssklower m -> m_len = sizeof (*oldp); 49541595Ssklower } 49641595Ssklower 497*45895Ssklower 498*45895Ssklower pk_checksockaddr (m) 499*45895Ssklower struct mbuf *m; 500*45895Ssklower { 501*45895Ssklower register struct sockaddr_x25 *sa = mtod (m, struct sockaddr_x25 *); 502*45895Ssklower register char *cp; 503*45895Ssklower 504*45895Ssklower if (m -> m_len != sizeof (struct sockaddr_x25)) 505*45895Ssklower return (1); 506*45895Ssklower if (sa -> x25_family != AF_CCITT || 507*45895Ssklower sa -> x25_udlen > sizeof (sa -> x25_udata)) 508*45895Ssklower return (1); 509*45895Ssklower for (cp = sa -> x25_addr; *cp; cp++) { 510*45895Ssklower if (*cp < '0' || *cp > '9' || 511*45895Ssklower cp >= &sa -> x25_addr[sizeof (sa -> x25_addr) - 1]) 512*45895Ssklower return (1); 513*45895Ssklower } 514*45895Ssklower return (0); 515*45895Ssklower } 51641595Ssklower pk_send (lcp, m) 51745297Ssklower struct pklcd *lcp; 51841595Ssklower register struct mbuf *m; 51941595Ssklower { 520*45895Ssklower int mqbit = 0, error = 0; 521*45895Ssklower register struct x25_packet *xp; 52241595Ssklower 523*45895Ssklower if (m -> m_type == MT_OOBDATA) { 524*45895Ssklower if (lcp -> lcd_intrconf_pending) 525*45895Ssklower error = ETOOMANYREFS; 526*45895Ssklower if (m -> m_pkthdr.len > 32) 527*45895Ssklower error = EMSGSIZE; 528*45895Ssklower M_PREPEND(m, PKHEADERLN, M_WAITOK); 529*45895Ssklower if (m == 0 || error) 530*45895Ssklower goto bad; 531*45895Ssklower lcp -> lcd_template = m; 532*45895Ssklower *(mtod (m, octet *)) = 0; 533*45895Ssklower xp = mtod (m, struct x25_packet *); 534*45895Ssklower xp -> fmt_identifier = 1; 535*45895Ssklower xp -> packet_type = X25_INTERRUPT; 536*45895Ssklower SET_LCN(xp, lcp -> lcd_lcn); 537*45895Ssklower return (pk_output (lcp)); 538*45895Ssklower } 53941595Ssklower /* 54041595Ssklower * Application has elected (at call setup time) to prepend 54141595Ssklower * a control byte to each packet written indicating m-bit 54241595Ssklower * and q-bit status. Examine and then discard this byte. 54341595Ssklower */ 54441595Ssklower if (lcp -> lcd_flags & X25_MQBIT) { 54541595Ssklower if (m -> m_len < 1) { 54645297Ssklower m_freem (m); 54741595Ssklower return (EMSGSIZE); 54841595Ssklower } 549*45895Ssklower mqbit = *(mtod (m, u_char *)); 55041595Ssklower m -> m_len--; 55141936Ssklower m -> m_data++; 55245297Ssklower m -> m_pkthdr.len--; 55341595Ssklower } 55445297Ssklower if ((error = pk_fragment(lcp, m, mqbit & 0x80, mqbit &0x40, 1)) == 0) 55545297Ssklower error = pk_output (lcp); 55645297Ssklower return (error); 557*45895Ssklower bad: 558*45895Ssklower if (m) 559*45895Ssklower m_freem (m); 560*45895Ssklower return (error); 56141595Ssklower } 562