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