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