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