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