The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netccitt/pk_usrreq.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: pk_usrreq.c,v 1.26 2003/08/07 16:33:05 agc Exp $       */
    2 
    3 /*
    4  * Copyright (c) 1991, 1992, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * This code is derived from software contributed to Berkeley by the
    8  * Laboratory for Computation Vision and the Computer Science Department
    9  * of the University of British Columbia and the Computer Science
   10  * Department (IV) of the University of Erlangen-Nuremberg, Germany.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  *      @(#)pk_usrreq.c 8.2 (Berkeley) 1/9/95
   37  */
   38 
   39 /*
   40  * Copyright (c) 1984 University of British Columbia.
   41  * Copyright (c) 1992 Computer Science Department IV,
   42  *              University of Erlangen-Nuremberg, Germany.
   43  *
   44  * This code is derived from software contributed to Berkeley by the
   45  * Laboratory for Computation Vision and the Computer Science Department
   46  * of the University of British Columbia and the Computer Science
   47  * Department (IV) of the University of Erlangen-Nuremberg, Germany.
   48  *
   49  * Redistribution and use in source and binary forms, with or without
   50  * modification, are permitted provided that the following conditions
   51  * are met:
   52  * 1. Redistributions of source code must retain the above copyright
   53  *    notice, this list of conditions and the following disclaimer.
   54  * 2. Redistributions in binary form must reproduce the above copyright
   55  *    notice, this list of conditions and the following disclaimer in the
   56  *    documentation and/or other materials provided with the distribution.
   57  * 3. All advertising materials mentioning features or use of this software
   58  *    must display the following acknowledgement:
   59  *      This product includes software developed by the University of
   60  *      California, Berkeley and its contributors.
   61  * 4. Neither the name of the University nor the names of its contributors
   62  *    may be used to endorse or promote products derived from this software
   63  *    without specific prior written permission.
   64  *
   65  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   66  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   67  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   68  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   69  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   70  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   71  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   72  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   73  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   74  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   75  * SUCH DAMAGE.
   76  *
   77  *      @(#)pk_usrreq.c 8.2 (Berkeley) 1/9/95
   78  */
   79 
   80 #include <sys/cdefs.h>
   81 __KERNEL_RCSID(0, "$NetBSD: pk_usrreq.c,v 1.26 2003/08/07 16:33:05 agc Exp $");
   82 
   83 #include <sys/param.h>
   84 #include <sys/systm.h>
   85 #include <sys/mbuf.h>
   86 #include <sys/socket.h>
   87 #include <sys/socketvar.h>
   88 #include <sys/protosw.h>
   89 #include <sys/errno.h>
   90 #include <sys/ioctl.h>
   91 #include <sys/stat.h>
   92 #include <sys/proc.h>
   93 
   94 #include <net/if.h>
   95 #include <net/if_types.h>
   96 #include <net/route.h>
   97 
   98 #include <netccitt/x25.h>
   99 #include <netccitt/pk.h>
  100 #include <netccitt/pk_var.h>
  101 #include <netccitt/pk_extern.h>
  102 
  103 static void pk_setsockaddr __P((struct pklcd *, struct mbuf *));
  104 static void pk_setpeeraddr __P((struct pklcd *, struct mbuf *));
  105 static void old_to_new __P((struct mbuf *));
  106 static void new_to_old __P((struct mbuf *));
  107 
  108 static void
  109 pk_setsockaddr(lcp, nam)
  110         struct pklcd *lcp;
  111         struct mbuf *nam;
  112 {
  113 
  114         nam->m_len = sizeof(struct sockaddr_x25);
  115         bcopy(lcp->lcd_ceaddr, mtod(nam, caddr_t), (size_t)nam->m_len);
  116         if (lcp->lcd_flags & X25_OLDSOCKADDR)
  117                 new_to_old(nam);
  118 }
  119 
  120 static void
  121 pk_setpeeraddr(lcp, nam)
  122         struct pklcd *lcp;
  123         struct mbuf *nam;
  124 {
  125 
  126         nam->m_len = sizeof(struct sockaddr_x25);
  127         bcopy(lcp->lcd_craddr, mtod(nam, caddr_t), (size_t)nam->m_len);
  128         if (lcp->lcd_flags & X25_OLDSOCKADDR)
  129                 new_to_old(nam);
  130 }
  131 
  132 /*
  133  *
  134  *  X.25 Packet level protocol interface to socket abstraction.
  135  *
  136  *  Process an X.25 user request on a logical channel.  If this is a send
  137  *  request then m is the mbuf chain of the send data. If this is a timer
  138  *  expiration (called from the software clock routine) them timertype is
  139  *  the particular timer.
  140  *
  141  */
  142 int
  143 pk_usrreq(so, req, m, nam, control, p)
  144         struct socket *so;
  145         int req;
  146         struct mbuf *m, *nam, *control;
  147         struct proc *p;
  148 {
  149         struct pklcd *lcp;
  150         int s;
  151         int error = 0;
  152 
  153         if (req == PRU_CONTROL)
  154                 return (pk_control(so, (long)m, (caddr_t)nam,
  155                     (struct ifnet *)control, p));
  156 
  157         s = splsoftnet();
  158         lcp = (struct pklcd *)so->so_pcb;
  159 #ifdef DIAGNOSTIC
  160         if (req != PRU_SEND && req != PRU_SENDOOB && control)
  161                 panic("pk_usrreq: unexpected control mbuf");
  162 #endif
  163         if (lcp == 0 && req != PRU_ATTACH) {
  164                 error = EINVAL;
  165                 goto release;
  166         }
  167 
  168         /*
  169                 pk_trace (pkcbhead, TR_USER, (struct pklcd *)0,
  170                         req, (struct x25_packet *)0);
  171         */
  172         switch (req) {
  173 
  174                 /*
  175                  * X.25 attaches to socket via PRU_ATTACH and allocates a
  176                  * logical channel descriptor.  If the socket is to  receive
  177                  * connections, then the LISTEN state is entered.
  178                  */
  179         case PRU_ATTACH:
  180                 if (lcp != 0) {
  181                         error = EISCONN;
  182                         break;
  183                 }
  184                 lcp = pk_attach(so);
  185                 if (lcp == 0)
  186                         error = ENOBUFS;
  187                 break;
  188 
  189                 /*
  190                  * Detach a logical channel from the socket. If the state of
  191                  * the channel is embryonic, simply discard it. Otherwise we
  192                  * have to initiate a PRU_DISCONNECT which will finish later.
  193                  */
  194         case PRU_DETACH:
  195                 pk_disconnect(lcp);
  196                 break;
  197 
  198                 /*
  199                  * Give the socket an address.
  200                  */
  201         case PRU_BIND:
  202                 if (nam->m_len == sizeof(struct x25_sockaddr))
  203                         old_to_new(nam);
  204                 error = pk_bind(lcp, nam);
  205                 break;
  206 
  207                 /*
  208                  * Prepare to accept connections.
  209                  */
  210         case PRU_LISTEN:
  211                 error = pk_listen(lcp);
  212                 break;
  213 
  214                 /*
  215                  * Initiate a CALL REQUEST to peer entity. Enter state
  216                  * SENT_CALL and mark the socket as connecting. Set timer
  217                  * waiting for CALL ACCEPT or CLEAR.
  218                  */
  219         case PRU_CONNECT:
  220                 if (nam->m_len == sizeof(struct x25_sockaddr))
  221                         old_to_new(nam);
  222                 if (pk_checksockaddr(nam)) {
  223                         error = EINVAL;
  224                         break;
  225                 }
  226                 error = pk_connect(lcp, mtod(nam, struct sockaddr_x25 *));
  227                 break;
  228 
  229         case PRU_CONNECT2:
  230                 error = EOPNOTSUPP;
  231                 break;
  232 
  233                 /*
  234                  * Initiate a disconnect to peer entity via a CLEAR REQUEST
  235                  * packet. The socket will be disconnected when we receive a
  236                  * confirmation or a clear collision.
  237                  */
  238         case PRU_DISCONNECT:
  239                 pk_disconnect(lcp);
  240                 break;
  241 
  242                 /*
  243                  * Accept an INCOMING CALL. Most of the work has already been
  244                  * done by pk_input. Just return the callers address to the
  245                  * user.
  246                  */
  247         case PRU_ACCEPT:
  248                 if (lcp->lcd_craddr == NULL)
  249                         break;
  250                 pk_setpeeraddr(lcp, nam);
  251                 break;
  252 
  253         case PRU_SHUTDOWN:
  254                 socantsendmore(so);
  255                 break;
  256 
  257                 /*
  258                  * After a receive, we should send a RR.
  259                  */
  260         case PRU_RCVD:
  261                 pk_flowcontrol(lcp, /* sbspace (&so -> so_rcv) <= */ 0, 1);
  262                 break;
  263 
  264                 /*
  265                  * Do send by placing data on the socket output queue.
  266                  */
  267         case PRU_SEND:
  268                 if (control) {
  269                         struct cmsghdr *ch = mtod(m, struct cmsghdr *);
  270                         control->m_len -= sizeof(*ch);
  271                         control->m_data += sizeof(*ch);
  272                         error = pk_ctloutput(PRCO_SETOPT, so, ch->cmsg_level,
  273                                              ch->cmsg_type, &control);
  274                         if (error)
  275                                 break;
  276                 }
  277                 if (m)
  278                         error = pk_send(m, lcp);
  279                 break;
  280 
  281                 /*
  282                  * Abort a virtual circuit. For example all completed calls
  283                  * waiting acceptance.
  284                  */
  285         case PRU_ABORT:
  286                 pk_disconnect(lcp);
  287                 break;
  288 
  289         case PRU_SENSE:
  290                 /*
  291                  * stat: don't bother with a blocksize.
  292                  */
  293                 splx(s);
  294                 return (0);
  295 
  296                 /*
  297                  * Receive INTERRUPT packet.
  298                  */
  299         case PRU_RCVOOB:
  300                 if (so->so_options & SO_OOBINLINE) {
  301                         struct mbuf *n = so->so_rcv.sb_mb;
  302                         if (n && n->m_type == MT_OOBDATA) {
  303                                 unsigned        len = n->m_pkthdr.len;
  304                                 so->so_rcv.sb_mb = n->m_nextpkt;
  305                                 SB_EMPTY_FIXUP(&so->so_rcv);
  306                                 if (len != n->m_len &&
  307                                     (n = m_pullup(n, len)) == 0)
  308                                         break;
  309                                 m->m_len = len;
  310                                 bcopy(mtod(m, caddr_t), mtod(n, caddr_t), len);
  311                                 m_freem(n);
  312                         }
  313                         break;
  314                 }
  315                 m->m_len = 1;
  316                 *mtod(m, char *) = lcp->lcd_intrdata;
  317                 break;
  318 
  319                 /*
  320                  * Send INTERRUPT packet.
  321                  */
  322         case PRU_SENDOOB:
  323                 if (control) {
  324                         struct cmsghdr *ch = mtod(m, struct cmsghdr *);
  325                         control->m_len -= sizeof(*ch);
  326                         control->m_data += sizeof(*ch);
  327                         error = pk_ctloutput(PRCO_SETOPT, so, ch->cmsg_level,
  328                                              ch->cmsg_type, &control);
  329                         if (error)
  330                                 break;
  331                 }
  332                 if (m) {
  333                         MCHTYPE(m, MT_OOBDATA);
  334                         error = pk_send(m, lcp);
  335                 }
  336                 break;
  337 
  338         case PRU_SOCKADDR:
  339                 if (lcp->lcd_ceaddr == 0) {
  340                         error = EADDRNOTAVAIL;
  341                         break;
  342                 }
  343                 pk_setsockaddr(lcp, nam);
  344                 break;
  345 
  346         case PRU_PEERADDR:
  347                 if (lcp->lcd_state != DATA_TRANSFER) {
  348                         error = ENOTCONN;
  349                         break;
  350                 }
  351                 pk_setpeeraddr(lcp, nam);
  352                 break;
  353 
  354         default:
  355                 panic("pk_usrreq");
  356         }
  357 
  358 release:
  359         splx(s);
  360         return (error);
  361 }
  362 
  363 /*
  364  * If you want to use UBC X.25 level 3 in conjunction with some other X.25
  365  * level 2 driver, have the ifp -> if_ioctl routine assign pk_start to ia ->
  366  * ia_start when called with SIOCSIFCONF_X25.
  367  */
  368 /* ARGSUSED */
  369 int
  370 pk_start(lcp)
  371         struct pklcd *lcp;
  372 {
  373         pk_output(lcp);
  374         return (0);             /* XXX pk_output should return a value */
  375 }
  376 
  377 struct sockaddr_x25 pk_sockmask = {
  378         offsetof(struct sockaddr_x25, x25_addr[0]),     /* x25_len */
  379         0,                      /* x25_family */
  380         -1,                     /* x25_net id */
  381 };
  382 
  383 /* ARGSUSED */
  384 int
  385 pk_control(so, cmd, data, ifp, p)
  386         struct socket *so;
  387         u_long cmd;
  388         caddr_t data;
  389         struct ifnet *ifp;
  390         struct proc *p;
  391 {
  392         struct ifreq_x25 *ifr = (struct ifreq_x25 *) data;
  393         struct ifaddr *ifa = 0;
  394         struct x25_ifaddr *ia = 0;
  395         int             error = 0, s, old_maxlcn;
  396 
  397         /*
  398          * Find address for this interface, if it exists.
  399          */
  400         if (ifp)
  401                 for (ifa = ifp->if_addrlist.tqh_first; ifa != 0;
  402                      ifa = ifa->ifa_list.tqe_next)
  403                         if (ifa->ifa_addr->sa_family == AF_CCITT)
  404                                 break;
  405 
  406         ia = (struct x25_ifaddr *) ifa;
  407         switch (cmd) {
  408         case SIOCGIFCONF_X25:
  409                 if (ifa == 0)
  410                         return (EADDRNOTAVAIL);
  411                 ifr->ifr_xc = ia->ia_xc;
  412                 return (0);
  413 
  414         case SIOCSIFCONF_X25:
  415                 if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag)))
  416                         return (EPERM);
  417                 if (ifp == 0)
  418                         panic("pk_control");
  419                 if (ifa == (struct ifaddr *) 0) {
  420                         MALLOC(ia, struct x25_ifaddr *, sizeof(*ia),
  421                                M_IFADDR, M_WAITOK);
  422                         if (ia == 0)
  423                                 return (ENOBUFS);
  424                         bzero((caddr_t) ia, sizeof(*ia));
  425                         TAILQ_INSERT_TAIL(&ifp->if_addrlist, &ia->ia_ifa,
  426                                           ifa_list);
  427                         ifa = &ia->ia_ifa;
  428                         IFAREF(ifa);
  429                         ifa->ifa_netmask = (struct sockaddr *) & pk_sockmask;
  430                         ifa->ifa_addr = (struct sockaddr *) & ia->ia_xc.xc_addr;
  431                         ifa->ifa_dstaddr = (struct sockaddr *) & ia->ia_dstaddr;        /* XXX */
  432                         ia->ia_ifp = ifp;
  433                         ia->ia_dstaddr.x25_family = AF_CCITT;
  434                         ia->ia_dstaddr.x25_len = pk_sockmask.x25_len;
  435                 } else if (ISISO8802(ifp) == 0) {
  436                         rtinit(ifa, (int) RTM_DELETE, 0);
  437                 }
  438                 old_maxlcn = ia->ia_maxlcn;
  439                 ia->ia_xc = ifr->ifr_xc;
  440                 ia->ia_dstaddr.x25_net = ia->ia_xc.xc_addr.x25_net;
  441                 if (ia->ia_maxlcn != old_maxlcn && old_maxlcn != 0) {
  442                         /* VERY messy XXX */
  443                         struct pkcb *pkp;
  444                         FOR_ALL_PKCBS(pkp)
  445                                 if (pkp->pk_ia == ia)
  446                                 pk_resize(pkp);
  447                 }
  448                 /*
  449                  * Give the interface a chance to initialize if this
  450 p                * is its first address, and to validate the address.
  451                  */
  452                 ia->ia_start = pk_start;
  453                 s = splnet();
  454                 if (ifp->if_ioctl)
  455                         error = (*ifp->if_ioctl) (ifp, SIOCSIFCONF_X25,
  456                                                   (caddr_t) ifa);
  457                 if (error)
  458                         ifp->if_flags &= ~IFF_UP;
  459                 else if (ISISO8802(ifp) == 0)
  460                         error = rtinit(ifa, (int) RTM_ADD, RTF_UP);
  461                 splx(s);
  462                 return (error);
  463 
  464         default:
  465                 if (ifp == 0 || ifp->if_ioctl == 0)
  466                         return (EOPNOTSUPP);
  467                 return ((*ifp->if_ioctl) (ifp, cmd, data));
  468         }
  469 }
  470 
  471 int
  472 pk_ctloutput(cmd, so, level, optname, mp)
  473         struct socket  *so;
  474         struct mbuf   **mp;
  475         int             cmd, level, optname;
  476 {
  477         struct proc *p = curproc;               /* XXX */
  478         struct mbuf *m = *mp;
  479         struct pklcd *lcp = (struct pklcd *) so->so_pcb;
  480         int             error = EOPNOTSUPP;
  481 
  482         if (m == 0)
  483                 return (EINVAL);
  484         if (cmd == PRCO_SETOPT)
  485                 switch (optname) {
  486                 case PK_FACILITIES:
  487                         if (m == 0)
  488                                 return (EINVAL);
  489                         lcp->lcd_facilities = m;
  490                         *mp = 0;
  491                         return (0);
  492 
  493                 case PK_ACCTFILE:
  494                         if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag)))
  495                                 error = EPERM;
  496                         else if (m->m_len)
  497                                 error = pk_accton(mtod(m, char *));
  498                         else
  499                                 error = pk_accton((char *) 0);
  500                         break;
  501 
  502                 case PK_RTATTACH:
  503                         error = pk_rtattach(so, m);
  504                         break;
  505 
  506                 case PK_PRLISTEN:
  507                         error = pk_user_protolisten(mtod(m, u_char *));
  508                 }
  509         if (*mp) {
  510                 (void) m_freem(*mp);
  511                 *mp = 0;
  512         }
  513         return (error);
  514 
  515 }
  516 
  517 
  518 /*
  519  * Do an in-place conversion of an "old style"
  520  * socket address to the new style
  521  */
  522 
  523 static void
  524 old_to_new(m)
  525         struct mbuf *m;
  526 {
  527         struct x25_sockaddr *oldp;
  528         struct sockaddr_x25 *newp;
  529         char  *ocp, *ncp;
  530         struct sockaddr_x25 new;
  531 
  532         oldp = mtod(m, struct x25_sockaddr *);
  533         newp = &new;
  534         bzero((caddr_t) newp, sizeof(*newp));
  535 
  536         newp->x25_family = AF_CCITT;
  537         newp->x25_len = sizeof(*newp);
  538         newp->x25_opts.op_flags = (oldp->xaddr_facilities & X25_REVERSE_CHARGE)
  539                 | X25_MQBIT | X25_OLDSOCKADDR;
  540         if (oldp->xaddr_facilities & XS_HIPRIO) /* Datapac specific */
  541                 newp->x25_opts.op_psize = X25_PS128;
  542         bcopy((caddr_t) oldp->xaddr_addr, newp->x25_addr,
  543               (unsigned) min(oldp->xaddr_len, sizeof(newp->x25_addr) - 1));
  544         if (bcmp((caddr_t) oldp->xaddr_proto, newp->x25_udata, 4) != 0) {
  545                 bcopy((caddr_t) oldp->xaddr_proto, newp->x25_udata, 4);
  546                 newp->x25_udlen = 4;
  547         }
  548         ocp = (caddr_t) oldp->xaddr_userdata;
  549         ncp = newp->x25_udata + 4;
  550         while (*ocp && ocp < (caddr_t) oldp->xaddr_userdata + 12) {
  551                 if (newp->x25_udlen == 0)
  552                         newp->x25_udlen = 4;
  553                 *ncp++ = *ocp++;
  554                 newp->x25_udlen++;
  555         }
  556         bcopy((caddr_t) newp, mtod(m, char *), sizeof(*newp));
  557         m->m_len = sizeof(*newp);
  558 }
  559 
  560 /*
  561  * Do an in-place conversion of a new style
  562  * socket address to the old style
  563  */
  564 
  565 static void
  566 new_to_old(m)
  567         struct mbuf *m;
  568 {
  569         struct x25_sockaddr *oldp;
  570         struct sockaddr_x25 *newp;
  571         char  *ocp, *ncp;
  572         struct x25_sockaddr old;
  573 
  574         oldp = &old;
  575         newp = mtod(m, struct sockaddr_x25 *);
  576         bzero((caddr_t) oldp, sizeof(*oldp));
  577 
  578         oldp->xaddr_facilities = newp->x25_opts.op_flags & X25_REVERSE_CHARGE;
  579         if (newp->x25_opts.op_psize == X25_PS128)
  580                 oldp->xaddr_facilities |= XS_HIPRIO;    /* Datapac specific */
  581         ocp = (char *) oldp->xaddr_addr;
  582         ncp = newp->x25_addr;
  583         while (*ncp) {
  584                 *ocp++ = *ncp++;
  585                 oldp->xaddr_len++;
  586         }
  587 
  588         bcopy(newp->x25_udata, (caddr_t) oldp->xaddr_proto, 4);
  589         if (newp->x25_udlen > 4)
  590                 bcopy(newp->x25_udata + 4, (caddr_t) oldp->xaddr_userdata,
  591                       (unsigned) (newp->x25_udlen - 4));
  592 
  593         bcopy((caddr_t) oldp, mtod(m, char *), sizeof(*oldp));
  594         m->m_len = sizeof(*oldp);
  595 }
  596 
  597 
  598 int
  599 pk_checksockaddr(m)
  600         struct mbuf    *m;
  601 {
  602         struct sockaddr_x25 *sa = mtod(m, struct sockaddr_x25 *);
  603         char  *cp;
  604 
  605         if (m->m_len != sizeof(struct sockaddr_x25))
  606                 return (1);
  607         if (sa->x25_family != AF_CCITT ||
  608             sa->x25_udlen > sizeof(sa->x25_udata))
  609                 return (1);
  610         for (cp = sa->x25_addr; *cp; cp++) {
  611                 if (*cp < '' || *cp > '9' ||
  612                     cp >= &sa->x25_addr[sizeof(sa->x25_addr) - 1])
  613                         return (1);
  614         }
  615         return (0);
  616 }
  617 
  618 int
  619 pk_send(m, v)
  620         struct mbuf *m;
  621         void *v;
  622 {
  623         struct pklcd   *lcp = v;
  624         int             mqbit = 0, error = 0;
  625         struct x25_packet *xp;
  626         struct socket *so;
  627 
  628         if (m->m_type == MT_OOBDATA) {
  629                 if (lcp->lcd_intrconf_pending)
  630                         error = ETOOMANYREFS;
  631                 if (m->m_pkthdr.len > 32)
  632                         error = EMSGSIZE;
  633                 M_PREPEND(m, PKHEADERLN, M_WAITOK);
  634                 if (m == 0 || error)
  635                         goto bad;
  636                 *(mtod(m, octet *)) = 0;
  637                 xp = mtod(m, struct x25_packet *);
  638                 X25SBITS(xp->bits, fmt_identifier, 1);
  639                 xp->packet_type = X25_INTERRUPT;
  640                 SET_LCN(xp, lcp->lcd_lcn);
  641                 sbinsertoob((so = lcp->lcd_so) ?
  642                             &so->so_snd : &lcp->lcd_sb, m);
  643                 goto send;
  644         }
  645         /*
  646          * Application has elected (at call setup time) to prepend
  647          * a control byte to each packet written indicating m-bit
  648          * and q-bit status.  Examine and then discard this byte.
  649          */
  650         if (lcp->lcd_flags & X25_MQBIT) {
  651                 if (m->m_len < 1) {
  652                         m_freem(m);
  653                         return (EMSGSIZE);
  654                 }
  655                 mqbit = *(mtod(m, u_char *));
  656                 m->m_len--;
  657                 m->m_data++;
  658                 m->m_pkthdr.len--;
  659         }
  660         error = pk_fragment(lcp, m, mqbit & 0x80, mqbit & 0x40, 1);
  661 send:
  662         if (error == 0 && lcp->lcd_state == DATA_TRANSFER)
  663                 lcp->lcd_send(lcp);     /* XXXXXXXXX fix pk_output!!! */
  664         return (error);
  665 bad:
  666         if (m)
  667                 m_freem(m);
  668         return (error);
  669 }

Cache object: 61cb7d2a52909428bb9dd40b392d2434


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.