|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * Copyright (c) 1984, 1985, 1986, 1987, 1993
27: * The Regents of the University of California. All rights reserved.
28: *
29: * Redistribution and use in source and binary forms, with or without
30: * modification, are permitted provided that the following conditions
31: * are met:
32: * 1. Redistributions of source code must retain the above copyright
33: * notice, this list of conditions and the following disclaimer.
34: * 2. Redistributions in binary form must reproduce the above copyright
35: * notice, this list of conditions and the following disclaimer in the
36: * documentation and/or other materials provided with the distribution.
37: * 3. All advertising materials mentioning features or use of this software
38: * must display the following acknowledgement:
39: * This product includes software developed by the University of
40: * California, Berkeley and its contributors.
41: * 4. Neither the name of the University nor the names of its contributors
42: * may be used to endorse or promote products derived from this software
43: * without specific prior written permission.
44: *
45: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55: * SUCH DAMAGE.
56: *
57: * @(#)idp_usrreq.c 8.1 (Berkeley) 6/10/93
58: */
59:
60: #include <sys/param.h>
61: #include <sys/malloc.h>
62: #include <sys/mbuf.h>
63: #include <sys/protosw.h>
64: #include <sys/socket.h>
65: #include <sys/socketvar.h>
66: #include <sys/errno.h>
67: #include <sys/stat.h>
68:
69: #include <net/if.h>
70: #include <net/route.h>
71:
72: #include <netns/ns.h>
73: #include <netns/ns_pcb.h>
74: #include <netns/ns_if.h>
75: #include <netns/idp.h>
76: #include <netns/idp_var.h>
77: #include <netns/ns_error.h>
78:
79: /*
80: * IDP protocol implementation.
81: */
82:
83: struct sockaddr_ns idp_ns = { sizeof(idp_ns), AF_NS };
84:
85: /*
86: * This may also be called for raw listeners.
87: */
88: idp_input(m, nsp)
89: struct mbuf *m;
90: register struct nspcb *nsp;
91: {
92: register struct idp *idp = mtod(m, struct idp *);
93: struct ifnet *ifp = m->m_pkthdr.rcvif;
94:
95: if (nsp==0)
96: panic("No nspcb");
97: /*
98: * Construct sockaddr format source address.
99: * Stuff source address and datagram in user buffer.
100: */
101: idp_ns.sns_addr = idp->idp_sna;
102: if (ns_neteqnn(idp->idp_sna.x_net, ns_zeronet) && ifp) {
103: register struct ifaddr *ifa;
104:
105: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
106: if (ifa->ifa_addr->sa_family == AF_NS) {
107: idp_ns.sns_addr.x_net =
108: IA_SNS(ifa)->sns_addr.x_net;
109: break;
110: }
111: }
112: }
113: nsp->nsp_rpt = idp->idp_pt;
114: if ( ! (nsp->nsp_flags & NSP_RAWIN) ) {
115: m->m_len -= sizeof (struct idp);
116: m->m_pkthdr.len -= sizeof (struct idp);
117: m->m_data += sizeof (struct idp);
118: }
119: if (sbappendaddr(&nsp->nsp_socket->so_rcv, (struct sockaddr *)&idp_ns,
120: m, (struct mbuf *)0) == 0)
121: goto bad;
122: sorwakeup(nsp->nsp_socket);
123: return;
124: bad:
125: m_freem(m);
126: }
127:
128: idp_abort(nsp)
129: struct nspcb *nsp;
130: {
131: struct socket *so = nsp->nsp_socket;
132:
133: ns_pcbdisconnect(nsp);
134: soisdisconnected(so);
135: }
136: /*
137: * Drop connection, reporting
138: * the specified error.
139: */
140: struct nspcb *
141: idp_drop(nsp, errno)
142: register struct nspcb *nsp;
143: int errno;
144: {
145: struct socket *so = nsp->nsp_socket;
146:
147: /*
148: * someday, in the xerox world
149: * we will generate error protocol packets
150: * announcing that the socket has gone away.
151: */
152: /*if (TCPS_HAVERCVDSYN(tp->t_state)) {
153: tp->t_state = TCPS_CLOSED;
154: (void) tcp_output(tp);
155: }*/
156: so->so_error = errno;
157: ns_pcbdisconnect(nsp);
158: soisdisconnected(so);
159: }
160:
161: int noIdpRoute;
162: idp_output(nsp, m0)
163: struct nspcb *nsp;
164: struct mbuf *m0;
165: {
166: register struct mbuf *m;
167: register struct idp *idp;
168: register struct socket *so;
169: register int len = 0;
170: register struct route *ro;
171: struct mbuf *mprev;
172: extern int idpcksum;
173:
174: /*
175: * Calculate data length.
176: */
177: for (m = m0; m; m = m->m_next) {
178: mprev = m;
179: len += m->m_len;
180: }
181: /*
182: * Make sure packet is actually of even length.
183: */
184:
185: if (len & 1) {
186: m = mprev;
187: if ((m->m_flags & M_EXT) == 0 &&
188: (m->m_len + m->m_data < &m->m_dat[MLEN])) {
189: m->m_len++;
190: } else {
191: struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA);
192:
193: if (m1 == 0) {
194: m_freem(m0);
195: return (ENOBUFS);
196: }
197: m1->m_len = 1;
198: * mtod(m1, char *) = 0;
199: m->m_next = m1;
200: }
201: m0->m_pkthdr.len++;
202: }
203:
204: /*
205: * Fill in mbuf with extended IDP header
206: * and addresses and length put into network format.
207: */
208: m = m0;
209: if (nsp->nsp_flags & NSP_RAWOUT) {
210: idp = mtod(m, struct idp *);
211: } else {
212: M_PREPEND(m, sizeof (struct idp), M_DONTWAIT);
213: if (m == 0)
214: return (ENOBUFS);
215: idp = mtod(m, struct idp *);
216: idp->idp_tc = 0;
217: idp->idp_pt = nsp->nsp_dpt;
218: idp->idp_sna = nsp->nsp_laddr;
219: idp->idp_dna = nsp->nsp_faddr;
220: len += sizeof (struct idp);
221: }
222:
223: idp->idp_len = htons((u_short)len);
224:
225: if (idpcksum) {
226: idp->idp_sum = 0;
227: len = ((len - 1) | 1) + 1;
228: idp->idp_sum = ns_cksum(m, len);
229: } else
230: idp->idp_sum = 0xffff;
231:
232: /*
233: * Output datagram.
234: */
235: so = nsp->nsp_socket;
236: if (so->so_options & SO_DONTROUTE)
237: return (ns_output(m, (struct route *)0,
238: (so->so_options & SO_BROADCAST) | NS_ROUTETOIF));
239: /*
240: * Use cached route for previous datagram if
241: * possible. If the previous net was the same
242: * and the interface was a broadcast medium, or
243: * if the previous destination was identical,
244: * then we are ok.
245: *
246: * NB: We don't handle broadcasts because that
247: * would require 3 subroutine calls.
248: */
249: ro = &nsp->nsp_route;
250: #ifdef ancient_history
251: /*
252: * I think that this will all be handled in ns_pcbconnect!
253: */
254: if (ro->ro_rt) {
255: if(ns_neteq(nsp->nsp_lastdst, idp->idp_dna)) {
256: /*
257: * This assumes we have no GH type routes
258: */
259: if (ro->ro_rt->rt_flags & RTF_HOST) {
260: if (!ns_hosteq(nsp->nsp_lastdst, idp->idp_dna))
261: goto re_route;
262:
263: }
264: if ((ro->ro_rt->rt_flags & RTF_GATEWAY) == 0) {
265: register struct ns_addr *dst =
266: &satons_addr(ro->ro_dst);
267: dst->x_host = idp->idp_dna.x_host;
268: }
269: /*
270: * Otherwise, we go through the same gateway
271: * and dst is already set up.
272: */
273: } else {
274: re_route:
275: RTFREE(ro->ro_rt);
276: ro->ro_rt = (struct rtentry *)0;
277: }
278: }
279: nsp->nsp_lastdst = idp->idp_dna;
280: #endif /* ancient_history */
281: if (noIdpRoute) ro = 0;
282: return (ns_output(m, ro, so->so_options & SO_BROADCAST));
283: }
284: /* ARGSUSED */
285: idp_ctloutput(req, so, level, name, value)
286: int req, level;
287: struct socket *so;
288: int name;
289: struct mbuf **value;
290: {
291: register struct mbuf *m;
292: struct nspcb *nsp = sotonspcb(so);
293: int mask, error = 0;
294: extern long ns_pexseq;
295:
296: if (nsp == NULL)
297: return (EINVAL);
298:
299: switch (req) {
300:
301: case PRCO_GETOPT:
302: if (value==NULL)
303: return (EINVAL);
304: m = m_get(M_DONTWAIT, MT_DATA);
305: if (m==NULL)
306: return (ENOBUFS);
307: switch (name) {
308:
309: case SO_ALL_PACKETS:
310: mask = NSP_ALL_PACKETS;
311: goto get_flags;
312:
313: case SO_HEADERS_ON_INPUT:
314: mask = NSP_RAWIN;
315: goto get_flags;
316:
317: case SO_HEADERS_ON_OUTPUT:
318: mask = NSP_RAWOUT;
319: get_flags:
320: m->m_len = sizeof(short);
321: *mtod(m, short *) = nsp->nsp_flags & mask;
322: break;
323:
324: case SO_DEFAULT_HEADERS:
325: m->m_len = sizeof(struct idp);
326: {
327: register struct idp *idp = mtod(m, struct idp *);
328: idp->idp_len = 0;
329: idp->idp_sum = 0;
330: idp->idp_tc = 0;
331: idp->idp_pt = nsp->nsp_dpt;
332: idp->idp_dna = nsp->nsp_faddr;
333: idp->idp_sna = nsp->nsp_laddr;
334: }
335: break;
336:
337: case SO_SEQNO:
338: m->m_len = sizeof(long);
339: *mtod(m, long *) = ns_pexseq++;
340: break;
341:
342: default:
343: error = EINVAL;
344: }
345: *value = m;
346: break;
347:
348: case PRCO_SETOPT:
349: switch (name) {
350: int *ok;
351:
352: case SO_ALL_PACKETS:
353: mask = NSP_ALL_PACKETS;
354: goto set_head;
355:
356: case SO_HEADERS_ON_INPUT:
357: mask = NSP_RAWIN;
358: goto set_head;
359:
360: case SO_HEADERS_ON_OUTPUT:
361: mask = NSP_RAWOUT;
362: set_head:
363: if (value && *value) {
364: ok = mtod(*value, int *);
365: if (*ok)
366: nsp->nsp_flags |= mask;
367: else
368: nsp->nsp_flags &= ~mask;
369: } else error = EINVAL;
370: break;
371:
372: case SO_DEFAULT_HEADERS:
373: {
374: register struct idp *idp
375: = mtod(*value, struct idp *);
376: nsp->nsp_dpt = idp->idp_pt;
377: }
378: break;
379: #ifdef NSIP
380:
381: case SO_NSIP_ROUTE:
382: error = nsip_route(*value);
383: break;
384: #endif /* NSIP */
385: default:
386: error = EINVAL;
387: }
388: if (value && *value)
389: m_freem(*value);
390: break;
391: }
392: return (error);
393: }
394:
395: /*ARGSUSED*/
396: idp_usrreq(so, req, m, nam, control)
397: struct socket *so;
398: int req;
399: struct mbuf *m, *nam, *control;
400: {
401: struct nspcb *nsp = sotonspcb(so);
402: int error = 0;
403:
404: if (req == PRU_CONTROL)
405: return (ns_control(so, (int)m, (caddr_t)nam,
406: (struct ifnet *)control));
407: if (control && control->m_len) {
408: error = EINVAL;
409: goto release;
410: }
411: if (nsp == NULL && req != PRU_ATTACH) {
412: error = EINVAL;
413: goto release;
414: }
415: switch (req) {
416:
417: case PRU_ATTACH:
418: if (nsp != NULL) {
419: error = EINVAL;
420: break;
421: }
422: error = ns_pcballoc(so, &nspcb);
423: if (error)
424: break;
425: error = soreserve(so, (u_long) 2048, (u_long) 2048);
426: if (error)
427: break;
428: break;
429:
430: case PRU_DETACH:
431: if (nsp == NULL) {
432: error = ENOTCONN;
433: break;
434: }
435: ns_pcbdetach(nsp);
436: break;
437:
438: case PRU_BIND:
439: error = ns_pcbbind(nsp, nam);
440: break;
441:
442: case PRU_LISTEN:
443: error = EOPNOTSUPP;
444: break;
445:
446: case PRU_CONNECT:
447: if (!ns_nullhost(nsp->nsp_faddr)) {
448: error = EISCONN;
449: break;
450: }
451: error = ns_pcbconnect(nsp, nam);
452: if (error == 0)
453: soisconnected(so);
454: break;
455:
456: case PRU_CONNECT2:
457: error = EOPNOTSUPP;
458: break;
459:
460: case PRU_ACCEPT:
461: error = EOPNOTSUPP;
462: break;
463:
464: case PRU_DISCONNECT:
465: if (ns_nullhost(nsp->nsp_faddr)) {
466: error = ENOTCONN;
467: break;
468: }
469: ns_pcbdisconnect(nsp);
470: soisdisconnected(so);
471: break;
472:
473: case PRU_SHUTDOWN:
474: socantsendmore(so);
475: break;
476:
477: case PRU_SEND:
478: {
479: struct ns_addr laddr;
480: int s;
481:
482: if (nam) {
483: laddr = nsp->nsp_laddr;
484: if (!ns_nullhost(nsp->nsp_faddr)) {
485: error = EISCONN;
486: break;
487: }
488: /*
489: * Must block input while temporarily connected.
490: */
491: s = splnet();
492: error = ns_pcbconnect(nsp, nam);
493: if (error) {
494: splx(s);
495: break;
496: }
497: } else {
498: if (ns_nullhost(nsp->nsp_faddr)) {
499: error = ENOTCONN;
500: break;
501: }
502: }
503: error = idp_output(nsp, m);
504: m = NULL;
505: if (nam) {
506: ns_pcbdisconnect(nsp);
507: splx(s);
508: nsp->nsp_laddr.x_host = laddr.x_host;
509: nsp->nsp_laddr.x_port = laddr.x_port;
510: }
511: }
512: break;
513:
514: case PRU_ABORT:
515: ns_pcbdetach(nsp);
516: sofree(so);
517: soisdisconnected(so);
518: break;
519:
520: case PRU_SOCKADDR:
521: ns_setsockaddr(nsp, nam);
522: break;
523:
524: case PRU_PEERADDR:
525: ns_setpeeraddr(nsp, nam);
526: break;
527:
528: case PRU_SENSE:
529: /*
530: * stat: don't bother with a blocksize.
531: */
532: return (0);
533:
534: case PRU_SENDOOB:
535: case PRU_FASTTIMO:
536: case PRU_SLOWTIMO:
537: case PRU_PROTORCV:
538: case PRU_PROTOSEND:
539: error = EOPNOTSUPP;
540: break;
541:
542: case PRU_CONTROL:
543: case PRU_RCVD:
544: case PRU_RCVOOB:
545: return (EOPNOTSUPP); /* do not free mbuf's */
546:
547: default:
548: panic("idp_usrreq");
549: }
550: release:
551: if (control != NULL)
552: m_freem(control);
553: if (m != NULL)
554: m_freem(m);
555: return (error);
556: }
557: /*ARGSUSED*/
558: idp_raw_usrreq(so, req, m, nam, control)
559: struct socket *so;
560: int req;
561: struct mbuf *m, *nam, *control;
562: {
563: int error = 0;
564: struct nspcb *nsp = sotonspcb(so);
565: extern struct nspcb nsrawpcb;
566:
567: switch (req) {
568:
569: case PRU_ATTACH:
570:
571: if (!(so->so_state & SS_PRIV) || (nsp != NULL)) {
572: error = EINVAL;
573: break;
574: }
575: error = ns_pcballoc(so, &nsrawpcb);
576: if (error)
577: break;
578: error = soreserve(so, (u_long) 2048, (u_long) 2048);
579: if (error)
580: break;
581: nsp = sotonspcb(so);
582: nsp->nsp_faddr.x_host = ns_broadhost;
583: nsp->nsp_flags = NSP_RAWIN | NSP_RAWOUT;
584: break;
585: default:
586: error = idp_usrreq(so, req, m, nam, control);
587: }
588: return (error);
589: }
590:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.