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