]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netccitt/pk_usrreq.c
ba1cb95000094f280162674c37543c10d694a053
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) University of British Columbia, 1984
24 * Copyright (C) Computer Science Department IV,
25 * University of Erlangen-Nuremberg, Germany, 1992
26 * Copyright (c) 1991, 1992, 1993
27 * The Regents of the University of California. All rights reserved.
29 * This code is derived from software contributed to Berkeley by the
30 * Laboratory for Computation Vision and the Computer Science Department
31 * of the the University of British Columbia and the Computer Science
32 * Department (IV) of the University of Erlangen-Nuremberg, Germany.
34 * Redistribution and use in source and binary forms, with or without
35 * modification, are permitted provided that the following conditions
37 * 1. Redistributions of source code must retain the above copyright
38 * notice, this list of conditions and the following disclaimer.
39 * 2. Redistributions in binary form must reproduce the above copyright
40 * notice, this list of conditions and the following disclaimer in the
41 * documentation and/or other materials provided with the distribution.
42 * 3. All advertising materials mentioning features or use of this software
43 * must display the following acknowledgement:
44 * This product includes software developed by the University of
45 * California, Berkeley and its contributors.
46 * 4. Neither the name of the University nor the names of its contributors
47 * may be used to endorse or promote products derived from this software
48 * without specific prior written permission.
50 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * @(#)pk_usrreq.c 8.1 (Berkeley) 6/10/93
65 #include <sys/param.h>
66 #include <sys/systm.h>
68 #include <sys/socket.h>
69 #include <sys/socketvar.h>
70 #include <sys/protosw.h>
71 #include <sys/errno.h>
72 #include <sys/ioctl.h>
74 #include <sys/malloc.h>
77 #include <net/if_types.h>
78 #include <net/route.h>
80 #include <netccitt/x25.h>
81 #include <netccitt/pk.h>
82 #include <netccitt/pk_var.h>
88 * X.25 Packet level protocol interface to socket abstraction.
90 * Process an X.25 user request on a logical channel. If this is a send
91 * request then m is the mbuf chain of the send data. If this is a timer
92 * expiration (called from the software clock routine) them timertype is
93 * the particular timer.
97 pk_usrreq (so
, req
, m
, nam
, control
)
100 register struct mbuf
*m
, *nam
;
101 struct mbuf
*control
;
103 register struct pklcd
*lcp
= (struct pklcd
*) so
-> so_pcb
;
104 register int error
= 0;
106 if (req
== PRU_CONTROL
)
107 return (pk_control (so
, (int)m
, (caddr_t
)nam
,
108 (struct ifnet
*)control
));
109 if (control
&& control
-> m_len
) {
113 if (lcp
== NULL
&& req
!= PRU_ATTACH
) {
119 pk_trace (pkcbhead, TR_USER, (struct pklcd *)0,
120 req, (struct x25_packet *)0);
125 * X.25 attaches to socket via PRU_ATTACH and allocates a logical
126 * channel descriptor. If the socket is to receive connections,
127 * then the LISTEN state is entered.
132 /* Socket already connected. */
135 lcp
= pk_attach (so
);
141 * Detach a logical channel from the socket. If the state of the
142 * channel is embryonic, simply discard it. Otherwise we have to
143 * initiate a PRU_DISCONNECT which will finish later.
150 * Give the socket an address.
153 if (nam
-> m_len
== sizeof (struct x25_sockaddr
))
155 error
= pk_bind (lcp
, nam
);
159 * Prepare to accept connections.
162 error
= pk_listen (lcp
);
166 * Initiate a CALL REQUEST to peer entity. Enter state SENT_CALL
167 * and mark the socket as connecting. Set timer waiting for
168 * CALL ACCEPT or CLEAR.
171 if (nam
-> m_len
== sizeof (struct x25_sockaddr
))
173 if (pk_checksockaddr (nam
))
175 error
= pk_connect (lcp
, mtod (nam
, struct sockaddr_x25
*));
179 * Initiate a disconnect to peer entity via a CLEAR REQUEST packet.
180 * The socket will be disconnected when we receive a confirmation
181 * or a clear collision.
188 * Accept an INCOMING CALL. Most of the work has already been done
189 * by pk_input. Just return the callers address to the user.
192 if (lcp
-> lcd_craddr
== NULL
)
194 bcopy ((caddr_t
)lcp
-> lcd_craddr
, mtod (nam
, caddr_t
),
195 sizeof (struct sockaddr_x25
));
196 nam
-> m_len
= sizeof (struct sockaddr_x25
);
197 if (lcp
-> lcd_flags
& X25_OLDSOCKADDR
)
202 * After a receive, we should send a RR.
205 pk_flowcontrol (lcp
, /*sbspace (&so -> so_rcv) <= */ 0, 1);
209 * Send INTERRUPT packet.
213 MGETHDR(m
, M_WAITOK
, MT_OOBDATA
);
214 m
-> m_pkthdr
.len
= m
-> m_len
= 1;
215 *mtod (m
, octet
*) = 0;
217 if (m
-> m_pkthdr
.len
> 32) {
222 MCHTYPE(m
, MT_OOBDATA
);
226 * Do send by placing data on the socket output queue.
230 register struct cmsghdr
*ch
= mtod (m
, struct cmsghdr
*);
231 control
-> m_len
-= sizeof (*ch
);
232 control
-> m_data
+= sizeof (*ch
);
233 error
= pk_ctloutput (PRCO_SETOPT
, so
, ch
-> cmsg_level
,
234 ch
-> cmsg_type
, &control
);
237 error
= pk_send (lcp
, m
);
241 * Abort a virtual circuit. For example all completed calls
242 * waiting acceptance.
248 /* Begin unimplemented hooks. */
260 ((struct stat
*)m
) -> st_blksize
= so
-> so_snd
.sb_hiwat
;
266 /* End unimplemented hooks. */
269 if (lcp
-> lcd_ceaddr
== 0)
270 return (EADDRNOTAVAIL
);
271 nam
-> m_len
= sizeof (struct sockaddr_x25
);
272 bcopy ((caddr_t
)lcp
-> lcd_ceaddr
, mtod (nam
, caddr_t
),
273 sizeof (struct sockaddr_x25
));
274 if (lcp
-> lcd_flags
& X25_OLDSOCKADDR
)
279 if (lcp
-> lcd_state
!= DATA_TRANSFER
)
281 nam
-> m_len
= sizeof (struct sockaddr_x25
);
282 bcopy (lcp
-> lcd_craddr
? (caddr_t
)lcp
-> lcd_craddr
:
283 (caddr_t
)lcp
-> lcd_ceaddr
,
284 mtod (nam
, caddr_t
), sizeof (struct sockaddr_x25
));
285 if (lcp
-> lcd_flags
& X25_OLDSOCKADDR
)
290 * Receive INTERRUPT packet.
293 if (so
-> so_options
& SO_OOBINLINE
) {
294 register struct mbuf
*n
= so
-> so_rcv
.sb_mb
;
295 if (n
&& n
-> m_type
== MT_OOBDATA
) {
296 unsigned len
= n
-> m_pkthdr
.len
;
297 so
-> so_rcv
.sb_mb
= n
-> m_nextpkt
;
298 if (len
!= n
-> m_len
&&
299 (n
= m_pullup (n
, len
)) == 0)
302 bcopy (mtod (m
, caddr_t
), mtod (n
, caddr_t
), len
);
308 *mtod (m
, char *) = lcp
-> lcd_intrdata
;
321 * If you want to use UBC X.25 level 3 in conjunction with some
322 * other X.25 level 2 driver, have the ifp -> if_ioctl routine
323 * assign pk_start to ia -> ia_start when called with SIOCSIFCONF_X25.
327 register struct pklcd
*lcp
;
330 return (0); /* XXX pk_output should return a value */
334 #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
336 struct sockaddr_x25 pk_sockmask
= {
337 _offsetof(struct sockaddr_x25
, x25_addr
[0]), /* x25_len */
343 pk_control (so
, cmd
, data
, ifp
)
347 register struct ifnet
*ifp
;
349 register struct ifreq_x25
*ifr
= (struct ifreq_x25
*)data
;
350 register struct ifaddr
*ifa
= 0;
351 register struct x25_ifaddr
*ia
= 0;
352 struct pklcd
*dev_lcp
= 0;
353 int error
, s
, old_maxlcn
;
357 * Find address for this interface, if it exists.
360 for (ifa
= ifp
-> if_addrlist
; ifa
; ifa
= ifa
-> ifa_next
)
361 if (ifa
-> ifa_addr
-> sa_family
== AF_CCITT
)
364 ia
= (struct x25_ifaddr
*)ifa
;
366 case SIOCGIFCONF_X25
:
368 return (EADDRNOTAVAIL
);
369 ifr
-> ifr_xc
= ia
-> ia_xc
;
372 case SIOCSIFCONF_X25
:
373 if ((so
->so_state
& SS_PRIV
) == 0)
376 panic ("pk_control");
377 if (ifa
== (struct ifaddr
*)0) {
378 register struct mbuf
*m
;
380 MALLOC(ia
, struct x25_ifaddr
*, sizeof (*ia
),
384 bzero ((caddr_t
)ia
, sizeof (*ia
));
385 if (ifa
= ifp
-> if_addrlist
) {
386 for ( ; ifa
-> ifa_next
; ifa
= ifa
-> ifa_next
)
388 ifa
-> ifa_next
= &ia
-> ia_ifa
;
390 ifp
-> if_addrlist
= &ia
-> ia_ifa
;
392 ifa
-> ifa_netmask
= (struct sockaddr
*)&pk_sockmask
;
393 ifa
-> ifa_addr
= (struct sockaddr
*)&ia
-> ia_xc
.xc_addr
;
394 ifa
-> ifa_dstaddr
= (struct sockaddr
*)&ia
-> ia_dstaddr
; /* XXX */
396 ia
-> ia_dstaddr
.x25_family
= AF_CCITT
;
397 ia
-> ia_dstaddr
.x25_len
= pk_sockmask
.x25_len
;
398 } else if (ISISO8802(ifp
) == 0) {
399 rtinit (ifa
, (int)RTM_DELETE
, 0);
401 old_maxlcn
= ia
-> ia_maxlcn
;
402 ia
-> ia_xc
= ifr
-> ifr_xc
;
403 ia
-> ia_dstaddr
.x25_net
= ia
-> ia_xc
.xc_addr
.x25_net
;
404 if (ia
-> ia_maxlcn
!= old_maxlcn
&& old_maxlcn
!= 0) {
406 register struct pkcb
*pkp
;
408 if (pkp
-> pk_ia
== ia
)
412 * Give the interface a chance to initialize if this
413 p * is its first address, and to validate the address.
415 ia
-> ia_start
= pk_start
;
418 error
= (*ifp
-> if_ioctl
)(ifp
, SIOCSIFCONF_X25
,
421 ifp
-> if_flags
&= ~IFF_UP
;
422 else if (ISISO8802(ifp
) == 0)
423 error
= rtinit (ifa
, (int)RTM_ADD
, RTF_UP
);
428 if (ifp
== 0 || ifp
-> if_ioctl
== 0)
430 return ((*ifp
-> if_ioctl
)(ifp
, cmd
, data
));
434 pk_ctloutput (cmd
, so
, level
, optname
, mp
)
437 int cmd
, level
, optname
;
439 register struct mbuf
*m
= *mp
;
440 register struct pklcd
*lcp
= (struct pklcd
*) so
-> so_pcb
;
441 int error
= EOPNOTSUPP
;
445 if (cmd
== PRCO_SETOPT
) switch (optname
) {
449 lcp
-> lcd_facilities
= m
;
454 if ((so
->so_state
& SS_PRIV
) == 0)
457 error
= pk_accton (mtod (m
, char *));
459 error
= pk_accton ((char *)0);
463 error
= pk_rtattach (so
, m
);
467 error
= pk_user_protolisten (mtod (m
, u_char
*));
470 (void) m_freem (*mp
);
479 * Do an in-place conversion of an "old style"
480 * socket address to the new style
485 register struct mbuf
*m
;
487 register struct x25_sockaddr
*oldp
;
488 register struct sockaddr_x25
*newp
;
489 register char *ocp
, *ncp
;
490 struct sockaddr_x25
new;
492 oldp
= mtod (m
, struct x25_sockaddr
*);
494 bzero ((caddr_t
)newp
, sizeof (*newp
));
496 newp
-> x25_family
= AF_CCITT
;
497 newp
-> x25_len
= sizeof(*newp
);
498 newp
-> x25_opts
.op_flags
= (oldp
-> xaddr_facilities
& X25_REVERSE_CHARGE
)
499 | X25_MQBIT
| X25_OLDSOCKADDR
;
500 if (oldp
-> xaddr_facilities
& XS_HIPRIO
) /* Datapac specific */
501 newp
-> x25_opts
.op_psize
= X25_PS128
;
502 bcopy ((caddr_t
)oldp
-> xaddr_addr
, newp
-> x25_addr
,
503 (unsigned)min (oldp
-> xaddr_len
, sizeof (newp
-> x25_addr
) - 1));
504 if (bcmp ((caddr_t
)oldp
-> xaddr_proto
, newp
-> x25_udata
, 4) != 0) {
505 bcopy ((caddr_t
)oldp
-> xaddr_proto
, newp
-> x25_udata
, 4);
506 newp
-> x25_udlen
= 4;
508 ocp
= (caddr_t
)oldp
-> xaddr_userdata
;
509 ncp
= newp
-> x25_udata
+ 4;
510 while (*ocp
&& ocp
< (caddr_t
)oldp
-> xaddr_userdata
+ 12) {
511 if (newp
-> x25_udlen
== 0)
512 newp
-> x25_udlen
= 4;
516 bcopy ((caddr_t
)newp
, mtod (m
, char *), sizeof (*newp
));
517 m
-> m_len
= sizeof (*newp
);
521 * Do an in-place conversion of a new style
522 * socket address to the old style
527 register struct mbuf
*m
;
529 register struct x25_sockaddr
*oldp
;
530 register struct sockaddr_x25
*newp
;
531 register char *ocp
, *ncp
;
532 struct x25_sockaddr old
;
535 newp
= mtod (m
, struct sockaddr_x25
*);
536 bzero ((caddr_t
)oldp
, sizeof (*oldp
));
538 oldp
-> xaddr_facilities
= newp
-> x25_opts
.op_flags
& X25_REVERSE_CHARGE
;
539 if (newp
-> x25_opts
.op_psize
== X25_PS128
)
540 oldp
-> xaddr_facilities
|= XS_HIPRIO
; /* Datapac specific */
541 ocp
= (char *)oldp
-> xaddr_addr
;
542 ncp
= newp
-> x25_addr
;
548 bcopy (newp
-> x25_udata
, (caddr_t
)oldp
-> xaddr_proto
, 4);
549 if (newp
-> x25_udlen
> 4)
550 bcopy (newp
-> x25_udata
+ 4, (caddr_t
)oldp
-> xaddr_userdata
,
551 (unsigned)(newp
-> x25_udlen
- 4));
553 bcopy ((caddr_t
)oldp
, mtod (m
, char *), sizeof (*oldp
));
554 m
-> m_len
= sizeof (*oldp
);
561 register struct sockaddr_x25
*sa
= mtod (m
, struct sockaddr_x25
*);
564 if (m
-> m_len
!= sizeof (struct sockaddr_x25
))
566 if (sa
-> x25_family
!= AF_CCITT
||
567 sa
-> x25_udlen
> sizeof (sa
-> x25_udata
))
569 for (cp
= sa
-> x25_addr
; *cp
; cp
++) {
570 if (*cp
< '0' || *cp
> '9' ||
571 cp
>= &sa
-> x25_addr
[sizeof (sa
-> x25_addr
) - 1])
579 register struct mbuf
*m
;
581 int mqbit
= 0, error
= 0;
582 register struct x25_packet
*xp
;
583 register struct socket
*so
;
585 if (m
-> m_type
== MT_OOBDATA
) {
586 if (lcp
-> lcd_intrconf_pending
)
587 error
= ETOOMANYREFS
;
588 if (m
-> m_pkthdr
.len
> 32)
590 M_PREPEND(m
, PKHEADERLN
, M_WAITOK
);
593 *(mtod (m
, octet
*)) = 0;
594 xp
= mtod (m
, struct x25_packet
*);
595 X25SBITS(xp
-> bits
, fmt_identifier
, 1);
596 xp
-> packet_type
= X25_INTERRUPT
;
597 SET_LCN(xp
, lcp
-> lcd_lcn
);
598 sbinsertoob ( (so
= lcp
-> lcd_so
) ?
599 &so
-> so_snd
: &lcp
-> lcd_sb
, m
);
603 * Application has elected (at call setup time) to prepend
604 * a control byte to each packet written indicating m-bit
605 * and q-bit status. Examine and then discard this byte.
607 if (lcp
-> lcd_flags
& X25_MQBIT
) {
608 if (m
-> m_len
< 1) {
612 mqbit
= *(mtod (m
, u_char
*));
617 error
= pk_fragment (lcp
, m
, mqbit
& 0x80, mqbit
& 0x40, 1);
619 if (error
== 0 && lcp
-> lcd_state
== DATA_TRANSFER
)
620 lcp
-> lcd_send (lcp
); /* XXXXXXXXX fix pk_output!!! */