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