|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
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.
11: *
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
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
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.
28: *
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.
33: *
34: * Redistribution and use in source and binary forms, with or without
35: * modification, are permitted provided that the following conditions
36: * are met:
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.
49: *
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
60: * SUCH DAMAGE.
61: *
62: * @(#)pk_usrreq.c 8.1 (Berkeley) 6/10/93
63: */
64:
65: #include <sys/param.h>
66: #include <sys/systm.h>
67: #include <sys/mbuf.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>
73: #include <sys/stat.h>
74: #include <sys/malloc.h>
75:
76: #include <net/if.h>
77: #include <net/if_types.h>
78: #include <net/route.h>
79:
80: #include <netccitt/x25.h>
81: #include <netccitt/pk.h>
82: #include <netccitt/pk_var.h>
83:
84: static old_to_new();
85: static new_to_old();
86: /*
87: *
88: * X.25 Packet level protocol interface to socket abstraction.
89: *
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.
94: *
95: */
96:
97: pk_usrreq (so, req, m, nam, control)
98: struct socket *so;
99: int req;
100: register struct mbuf *m, *nam;
101: struct mbuf *control;
102: {
103: register struct pklcd *lcp = (struct pklcd *) so -> so_pcb;
104: register int error = 0;
105:
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) {
110: error = EINVAL;
111: goto release;
112: }
113: if (lcp == NULL && req != PRU_ATTACH) {
114: error = EINVAL;
115: goto release;
116: }
117:
118: /*
119: pk_trace (pkcbhead, TR_USER, (struct pklcd *)0,
120: req, (struct x25_packet *)0);
121: */
122:
123: switch (req) {
124: /*
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.
128: */
129: case PRU_ATTACH:
130: if (lcp) {
131: error = EISCONN;
132: /* Socket already connected. */
133: break;
134: }
135: lcp = pk_attach (so);
136: if (lcp == 0)
137: error = ENOBUFS;
138: break;
139:
140: /*
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.
144: */
145: case PRU_DETACH:
146: pk_disconnect (lcp);
147: break;
148:
149: /*
150: * Give the socket an address.
151: */
152: case PRU_BIND:
153: if (nam -> m_len == sizeof (struct x25_sockaddr))
154: old_to_new (nam);
155: error = pk_bind (lcp, nam);
156: break;
157:
158: /*
159: * Prepare to accept connections.
160: */
161: case PRU_LISTEN:
162: error = pk_listen (lcp);
163: break;
164:
165: /*
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.
169: */
170: case PRU_CONNECT:
171: if (nam -> m_len == sizeof (struct x25_sockaddr))
172: old_to_new (nam);
173: if (pk_checksockaddr (nam))
174: return (EINVAL);
175: error = pk_connect (lcp, mtod (nam, struct sockaddr_x25 *));
176: break;
177:
178: /*
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.
182: */
183: case PRU_DISCONNECT:
184: pk_disconnect (lcp);
185: break;
186:
187: /*
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.
190: */
191: case PRU_ACCEPT:
192: if (lcp -> lcd_craddr == NULL)
193: break;
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)
198: new_to_old (nam);
199: break;
200:
201: /*
202: * After a receive, we should send a RR.
203: */
204: case PRU_RCVD:
205: pk_flowcontrol (lcp, /*sbspace (&so -> so_rcv) <= */ 0, 1);
206: break;
207:
208: /*
209: * Send INTERRUPT packet.
210: */
211: case PRU_SENDOOB:
212: if (m == 0) {
213: MGETHDR(m, M_WAITOK, MT_OOBDATA);
214: m -> m_pkthdr.len = m -> m_len = 1;
215: *mtod (m, octet *) = 0;
216: }
217: if (m -> m_pkthdr.len > 32) {
218: m_freem (m);
219: error = EMSGSIZE;
220: break;
221: }
222: MCHTYPE(m, MT_OOBDATA);
223: /* FALLTHROUGH */
224:
225: /*
226: * Do send by placing data on the socket output queue.
227: */
228: case PRU_SEND:
229: if (control) {
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);
235: }
236: if (error == 0 && m)
237: error = pk_send (lcp, m);
238: break;
239:
240: /*
241: * Abort a virtual circuit. For example all completed calls
242: * waiting acceptance.
243: */
244: case PRU_ABORT:
245: pk_disconnect (lcp);
246: break;
247:
248: /* Begin unimplemented hooks. */
249:
250: case PRU_SHUTDOWN:
251: error = EOPNOTSUPP;
252: break;
253:
254: case PRU_CONTROL:
255: error = EOPNOTSUPP;
256: break;
257:
258: case PRU_SENSE:
259: #ifdef BSD4_3
260: ((struct stat *)m) -> st_blksize = so -> so_snd.sb_hiwat;
261: #else
262: error = EOPNOTSUPP;
263: #endif
264: break;
265:
266: /* End unimplemented hooks. */
267:
268: case PRU_SOCKADDR:
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)
275: new_to_old (nam);
276: break;
277:
278: case PRU_PEERADDR:
279: if (lcp -> lcd_state != DATA_TRANSFER)
280: return (ENOTCONN);
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)
286: new_to_old (nam);
287: break;
288:
289: /*
290: * Receive INTERRUPT packet.
291: */
292: case PRU_RCVOOB:
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)
300: break;
301: m -> m_len = len;
302: bcopy (mtod (m, caddr_t), mtod (n, caddr_t), len);
303: m_freem (n);
304: }
305: break;
306: }
307: m -> m_len = 1;
308: *mtod (m, char *) = lcp -> lcd_intrdata;
309: break;
310:
311: default:
312: panic ("pk_usrreq");
313: }
314: release:
315: if (control != NULL)
316: m_freem (control);
317: return (error);
318: }
319:
320: /*
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.
324: */
325: /* ARGSUSED */
326: pk_start (lcp)
327: register struct pklcd *lcp;
328: {
329: pk_output (lcp);
330: return (0); /* XXX pk_output should return a value */
331: }
332:
333: #ifndef _offsetof
334: #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
335: #endif
336: struct sockaddr_x25 pk_sockmask = {
337: _offsetof(struct sockaddr_x25, x25_addr[0]), /* x25_len */
338: 0, /* x25_family */
339: -1, /* x25_net id */
340: };
341:
342: /*ARGSUSED*/
343: pk_control (so, cmd, data, ifp)
344: struct socket *so;
345: int cmd;
346: caddr_t data;
347: register struct ifnet *ifp;
348: {
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;
354: unsigned n;
355:
356: /*
357: * Find address for this interface, if it exists.
358: */
359: if (ifp)
360: for (ifa = ifp -> if_addrlist; ifa; ifa = ifa -> ifa_next)
361: if (ifa -> ifa_addr -> sa_family == AF_CCITT)
362: break;
363:
364: ia = (struct x25_ifaddr *)ifa;
365: switch (cmd) {
366: case SIOCGIFCONF_X25:
367: if (ifa == 0)
368: return (EADDRNOTAVAIL);
369: ifr -> ifr_xc = ia -> ia_xc;
370: return (0);
371:
372: case SIOCSIFCONF_X25:
373: if ((so->so_state & SS_PRIV) == 0)
374: return (EPERM);
375: if (ifp == 0)
376: panic ("pk_control");
377: if (ifa == (struct ifaddr *)0) {
378: register struct mbuf *m;
379:
380: MALLOC(ia, struct x25_ifaddr *, sizeof (*ia),
381: M_IFADDR, M_WAITOK);
382: if (ia == 0)
383: return (ENOBUFS);
384: bzero ((caddr_t)ia, sizeof (*ia));
385: if (ifa = ifp -> if_addrlist) {
386: for ( ; ifa -> ifa_next; ifa = ifa -> ifa_next)
387: ;
388: ifa -> ifa_next = &ia -> ia_ifa;
389: } else
390: ifp -> if_addrlist = &ia -> ia_ifa;
391: ifa = &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 */
395: ia -> ia_ifp = ifp;
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);
400: }
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) {
405: /* VERY messy XXX */
406: register struct pkcb *pkp;
407: FOR_ALL_PKCBS(pkp)
408: if (pkp -> pk_ia == ia)
409: pk_resize (pkp);
410: }
411: /*
412: * Give the interface a chance to initialize if this
413: p * is its first address, and to validate the address.
414: */
415: ia -> ia_start = pk_start;
416: s = splimp();
417: if (ifp -> if_ioctl)
418: error = (*ifp -> if_ioctl)(ifp, SIOCSIFCONF_X25,
419: (caddr_t) ifa);
420: if (error)
421: ifp -> if_flags &= ~IFF_UP;
422: else if (ISISO8802(ifp) == 0)
423: error = rtinit (ifa, (int)RTM_ADD, RTF_UP);
424: splx (s);
425: return (error);
426:
427: default:
428: if (ifp == 0 || ifp -> if_ioctl == 0)
429: return (EOPNOTSUPP);
430: return ((*ifp -> if_ioctl)(ifp, cmd, data));
431: }
432: }
433:
434: pk_ctloutput (cmd, so, level, optname, mp)
435: struct socket *so;
436: struct mbuf **mp;
437: int cmd, level, optname;
438: {
439: register struct mbuf *m = *mp;
440: register struct pklcd *lcp = (struct pklcd *) so -> so_pcb;
441: int error = EOPNOTSUPP;
442:
443: if (m == 0)
444: return (EINVAL);
445: if (cmd == PRCO_SETOPT) switch (optname) {
446: case PK_FACILITIES:
447: if (m == 0)
448: return (EINVAL);
449: lcp -> lcd_facilities = m;
450: *mp = 0;
451: return (0);
452:
453: case PK_ACCTFILE:
454: if ((so->so_state & SS_PRIV) == 0)
455: error = EPERM;
456: else if (m -> m_len)
457: error = pk_accton (mtod (m, char *));
458: else
459: error = pk_accton ((char *)0);
460: break;
461:
462: case PK_RTATTACH:
463: error = pk_rtattach (so, m);
464: break;
465:
466: case PK_PRLISTEN:
467: error = pk_user_protolisten (mtod (m, u_char *));
468: }
469: if (*mp) {
470: (void) m_freem (*mp);
471: *mp = 0;
472: }
473: return (error);
474:
475: }
476:
477:
478: /*
479: * Do an in-place conversion of an "old style"
480: * socket address to the new style
481: */
482:
483: static
484: old_to_new (m)
485: register struct mbuf *m;
486: {
487: register struct x25_sockaddr *oldp;
488: register struct sockaddr_x25 *newp;
489: register char *ocp, *ncp;
490: struct sockaddr_x25 new;
491:
492: oldp = mtod (m, struct x25_sockaddr *);
493: newp = &new;
494: bzero ((caddr_t)newp, sizeof (*newp));
495:
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;
507: }
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;
513: *ncp++ = *ocp++;
514: newp -> x25_udlen++;
515: }
516: bcopy ((caddr_t)newp, mtod (m, char *), sizeof (*newp));
517: m -> m_len = sizeof (*newp);
518: }
519:
520: /*
521: * Do an in-place conversion of a new style
522: * socket address to the old style
523: */
524:
525: static
526: new_to_old (m)
527: register struct mbuf *m;
528: {
529: register struct x25_sockaddr *oldp;
530: register struct sockaddr_x25 *newp;
531: register char *ocp, *ncp;
532: struct x25_sockaddr old;
533:
534: oldp = &old;
535: newp = mtod (m, struct sockaddr_x25 *);
536: bzero ((caddr_t)oldp, sizeof (*oldp));
537:
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;
543: while (*ncp) {
544: *ocp++ = *ncp++;
545: oldp -> xaddr_len++;
546: }
547:
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));
552:
553: bcopy ((caddr_t)oldp, mtod (m, char *), sizeof (*oldp));
554: m -> m_len = sizeof (*oldp);
555: }
556:
557:
558: pk_checksockaddr (m)
559: struct mbuf *m;
560: {
561: register struct sockaddr_x25 *sa = mtod (m, struct sockaddr_x25 *);
562: register char *cp;
563:
564: if (m -> m_len != sizeof (struct sockaddr_x25))
565: return (1);
566: if (sa -> x25_family != AF_CCITT ||
567: sa -> x25_udlen > sizeof (sa -> x25_udata))
568: return (1);
569: for (cp = sa -> x25_addr; *cp; cp++) {
570: if (*cp < '0' || *cp > '9' ||
571: cp >= &sa -> x25_addr[sizeof (sa -> x25_addr) - 1])
572: return (1);
573: }
574: return (0);
575: }
576:
577: pk_send (lcp, m)
578: struct pklcd *lcp;
579: register struct mbuf *m;
580: {
581: int mqbit = 0, error = 0;
582: register struct x25_packet *xp;
583: register struct socket *so;
584:
585: if (m -> m_type == MT_OOBDATA) {
586: if (lcp -> lcd_intrconf_pending)
587: error = ETOOMANYREFS;
588: if (m -> m_pkthdr.len > 32)
589: error = EMSGSIZE;
590: M_PREPEND(m, PKHEADERLN, M_WAITOK);
591: if (m == 0 || error)
592: goto bad;
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);
600: goto send;
601: }
602: /*
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.
606: */
607: if (lcp -> lcd_flags & X25_MQBIT) {
608: if (m -> m_len < 1) {
609: m_freem (m);
610: return (EMSGSIZE);
611: }
612: mqbit = *(mtod (m, u_char *));
613: m -> m_len--;
614: m -> m_data++;
615: m -> m_pkthdr.len--;
616: }
617: error = pk_fragment (lcp, m, mqbit & 0x80, mqbit & 0x40, 1);
618: send:
619: if (error == 0 && lcp -> lcd_state == DATA_TRANSFER)
620: lcp -> lcd_send (lcp); /* XXXXXXXXX fix pk_output!!! */
621: return (error);
622: bad:
623: if (m)
624: m_freem (m);
625: return (error);
626: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.