rename kda =>kdb
[unix-history] / usr / src / sys / netns / idp_usrreq.c
CommitLineData
8ae0e4b4 1/*
240edf1f
KS
2 * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California.
3 * All rights reserved.
8ae0e4b4 4 *
240edf1f
KS
5 * Redistribution and use in source and binary forms are permitted
6 * provided that this notice is preserved and that due credit is given
7 * to the University of California at Berkeley. The name of the University
8 * may not be used to endorse or promote products derived from this
9 * software without specific prior written permission. This software
10 * is provided ``as is'' without express or implied warranty.
11 *
12 * @(#)idp_usrreq.c 7.2 (Berkeley) %G%
8ae0e4b4 13 */
b1fca4bf
KS
14
15#include "param.h"
16#include "dir.h"
17#include "user.h"
18#include "mbuf.h"
19#include "protosw.h"
20#include "socket.h"
21#include "socketvar.h"
22#include "errno.h"
23#include "stat.h"
24
25#include "../net/if.h"
26#include "../net/route.h"
27
28#include "ns.h"
29#include "ns_pcb.h"
d2ec0713 30#include "ns_if.h"
b1fca4bf
KS
31#include "idp.h"
32#include "idp_var.h"
33#include "ns_error.h"
34
35/*
36 * IDP protocol implementation.
37 */
38
39struct sockaddr_ns idp_ns = { AF_NS };
40
2b169881
KS
41/*
42 * This may also be called for raw listeners.
43 */
d2ec0713 44idp_input(m, nsp, ifp)
b1fca4bf
KS
45 struct mbuf *m;
46 register struct nspcb *nsp;
d2ec0713 47 struct ifnet *ifp;
b1fca4bf
KS
48{
49 register struct idp *idp = mtod(m, struct idp *);
2b169881 50
d2ec0713 51 if (nsp==0)
19d8bb77 52 panic("No nspcb");
b1fca4bf
KS
53 /*
54 * Construct sockaddr format source address.
55 * Stuff source address and datagram in user buffer.
56 */
57 idp_ns.sns_addr = idp->idp_sna;
f1e269d4 58 if (ns_neteqnn(idp->idp_sna.x_net, ns_zeronet) && ifp) {
d2ec0713
KS
59 register struct ifaddr *ia;
60
be9760a9 61 for (ia = ifp->if_addrlist; ia; ia = ia->ifa_next) {
d2ec0713
KS
62 if (ia->ifa_addr.sa_family == AF_NS) {
63 idp_ns.sns_addr.x_net =
64 IA_SNS(ia)->sns_addr.x_net;
65 break;
66 }
67 }
68 }
b1fca4bf
KS
69 nsp->nsp_rpt = idp->idp_pt;
70 if ( ! (nsp->nsp_flags & NSP_RAWIN) ) {
71 m->m_len -= sizeof (struct idp);
72 m->m_off += sizeof (struct idp);
73 }
74 if (sbappendaddr(&nsp->nsp_socket->so_rcv, (struct sockaddr *)&idp_ns,
75 m, (struct mbuf *)0) == 0)
76 goto bad;
77 sorwakeup(nsp->nsp_socket);
78 return;
79bad:
80 m_freem(m);
81}
82
83idp_abort(nsp)
84 struct nspcb *nsp;
85{
86 struct socket *so = nsp->nsp_socket;
87
88 ns_pcbdisconnect(nsp);
89 soisdisconnected(so);
90}
2b169881
KS
91/*
92 * Drop connection, reporting
93 * the specified error.
94 */
95struct nspcb *
96idp_drop(nsp, errno)
97 register struct nspcb *nsp;
98 int errno;
99{
100 struct socket *so = nsp->nsp_socket;
101
102 /*
103 * someday, in the xerox world
104 * we will generate error protocol packets
105 * announcing that the socket has gone away.
106 */
107 /*if (TCPS_HAVERCVDSYN(tp->t_state)) {
108 tp->t_state = TCPS_CLOSED;
109 (void) tcp_output(tp);
110 }*/
111 so->so_error = errno;
112 ns_pcbdisconnect(nsp);
113 soisdisconnected(so);
114}
b1fca4bf 115
dac1d492 116int noIdpRoute;
b1fca4bf
KS
117idp_output(nsp, m0)
118 struct nspcb *nsp;
119 struct mbuf *m0;
120{
121 register struct mbuf *m;
122 register struct idp *idp;
123 register struct socket *so;
124 register int len = 0;
125 register struct route *ro;
126 struct mbuf *mprev;
127 extern int idpcksum;
128
129 /*
130 * Calculate data length.
131 */
132 for (m = m0; m; m = m->m_next) {
133 mprev = m;
134 len += m->m_len;
135 }
136 /*
137 * Make sure packet is actually of even length.
138 */
139
140 if (len & 1) {
141 m = mprev;
142 if (m->m_len + m->m_off < MMAXOFF) {
143 m->m_len++;
144 } else {
145 struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA);
146
14bdc762
KS
147 if (m1 == 0) {
148 m_freem(m0);
149 return (ENOBUFS);
150 }
b1fca4bf
KS
151 m1->m_len = 1;
152 m1->m_off = MMAXOFF - 1;
153 * mtod(m1, char *) = 0;
154 m->m_next = m1;
155 }
156 }
157
158 /*
159 * Fill in mbuf with extended IDP header
160 * and addresses and length put into network format.
161 */
162 if (nsp->nsp_flags & NSP_RAWOUT) {
163 m = m0;
164 idp = mtod(m, struct idp *);
165 } else {
166 m = m_get(M_DONTWAIT, MT_HEADER);
167 if (m == 0) {
168 m_freem(m0);
169 return (ENOBUFS);
170 }
f1e269d4
KS
171 m->m_off = MMAXOFF - sizeof (struct idp) - 2;
172 /* adjust to start on longword bdry
173 for NSIP on gould */
b1fca4bf
KS
174 m->m_len = sizeof (struct idp);
175 m->m_next = m0;
176 idp = mtod(m, struct idp *);
177 idp->idp_tc = 0;
178 idp->idp_pt = nsp->nsp_dpt;
179 idp->idp_sna = nsp->nsp_laddr;
180 idp->idp_dna = nsp->nsp_faddr;
181 len += sizeof (struct idp);
182 }
183
184 idp->idp_len = htons((u_short)len);
185
186 if (idpcksum) {
187 idp->idp_sum = 0;
188 len = ((len - 1) | 1) + 1;
189 idp->idp_sum = ns_cksum(m, len);
190 } else
191 idp->idp_sum = 0xffff;
192
193 /*
194 * Output datagram.
195 */
196 so = nsp->nsp_socket;
197 if (so->so_options & SO_DONTROUTE)
198 return (ns_output(m, (struct route *)0,
199 (so->so_options & SO_BROADCAST) | NS_ROUTETOIF));
200 /*
201 * Use cached route for previous datagram if
dac1d492
KS
202 * possible. If the previous net was the same
203 * and the interface was a broadcast medium, or
204 * if the previous destination was identical,
205 * then we are ok.
b1fca4bf
KS
206 *
207 * NB: We don't handle broadcasts because that
208 * would require 3 subroutine calls.
209 */
210 ro = &nsp->nsp_route;
dac1d492
KS
211#ifdef ancient_history
212 /*
213 * I think that this will all be handled in ns_pcbconnect!
214 */
215 if (ro->ro_rt) {
216 if(ns_neteq(nsp->nsp_lastdst, idp->idp_dna)) {
217 /*
218 * This assumes we have no GH type routes
219 */
220 if (ro->ro_rt->rt_flags & RTF_HOST) {
221 if (!ns_hosteq(nsp->nsp_lastdst, idp->idp_dna))
222 goto re_route;
223
224 }
225 if ((ro->ro_rt->rt_flags & RTF_GATEWAY) == 0) {
226 register struct ns_addr *dst =
227 &satons_addr(ro->ro_dst);
228 dst->x_host = idp->idp_dna.x_host;
229 }
230 /*
231 * Otherwise, we go through the same gateway
232 * and dst is already set up.
233 */
234 } else {
235 re_route:
236 RTFREE(ro->ro_rt);
237 ro->ro_rt = (struct rtentry *)0;
238 }
b1fca4bf 239 }
dac1d492
KS
240 nsp->nsp_lastdst = idp->idp_dna;
241#endif ancient_history
242 if (noIdpRoute) ro = 0;
b1fca4bf
KS
243 return (ns_output(m, ro, so->so_options & SO_BROADCAST));
244}
f97be0c9 245/* ARGSUSED */
b1fca4bf
KS
246idp_ctloutput(req, so, level, name, value)
247 int req, level;
248 struct socket *so;
249 int name;
250 struct mbuf **value;
251{
252 register struct mbuf *m;
253 struct nspcb *nsp = sotonspcb(so);
254 int mask, error = 0;
2b169881 255 extern long ns_pexseq;
b1fca4bf 256
f72426ee
KS
257 if (nsp == NULL)
258 return (EINVAL);
b1fca4bf
KS
259
260 switch (req) {
f72426ee 261
b1fca4bf 262 case PRCO_GETOPT:
f72426ee
KS
263 if (value==NULL)
264 return (EINVAL);
b1fca4bf 265 m = m_get(M_DONTWAIT, MT_DATA);
f72426ee
KS
266 if (m==NULL)
267 return (ENOBUFS);
b1fca4bf 268 switch (name) {
f72426ee 269
19d8bb77
KS
270 case SO_ALL_PACKETS:
271 mask = NSP_ALL_PACKETS;
272 goto get_flags;
273
b1fca4bf
KS
274 case SO_HEADERS_ON_INPUT:
275 mask = NSP_RAWIN;
276 goto get_flags;
f72426ee 277
b1fca4bf
KS
278 case SO_HEADERS_ON_OUTPUT:
279 mask = NSP_RAWOUT;
280 get_flags:
281 m->m_len = sizeof(short);
282 m->m_off = MMAXOFF - sizeof(short);
283 *mtod(m, short *) = nsp->nsp_flags & mask;
284 break;
f72426ee 285
b1fca4bf
KS
286 case SO_DEFAULT_HEADERS:
287 m->m_len = sizeof(struct idp);
288 m->m_off = MMAXOFF - sizeof(struct idp);
289 {
290 register struct idp *idp = mtod(m, struct idp *);
291 idp->idp_len = 0;
292 idp->idp_sum = 0;
293 idp->idp_tc = 0;
294 idp->idp_pt = nsp->nsp_dpt;
295 idp->idp_dna = nsp->nsp_faddr;
296 idp->idp_sna = nsp->nsp_laddr;
297 }
2b169881
KS
298 break;
299
300 case SO_SEQNO:
301 m->m_len = sizeof(long);
302 m->m_off = MMAXOFF - sizeof(long);
303 *mtod(m, long *) = ns_pexseq++;
f2412db0
KS
304 break;
305
306 default:
307 error = EINVAL;
b1fca4bf
KS
308 }
309 *value = m;
310 break;
f72426ee 311
b1fca4bf
KS
312 case PRCO_SETOPT:
313 switch (name) {
f97be0c9 314 int *ok;
b1fca4bf 315
19d8bb77
KS
316 case SO_ALL_PACKETS:
317 mask = NSP_ALL_PACKETS;
318 goto set_head;
319
b1fca4bf
KS
320 case SO_HEADERS_ON_INPUT:
321 mask = NSP_RAWIN;
322 goto set_head;
f72426ee 323
b1fca4bf
KS
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;
f72426ee 335
b1fca4bf
KS
336 case SO_DEFAULT_HEADERS:
337 {
338 register struct idp *idp
339 = mtod(*value, struct idp *);
340 nsp->nsp_dpt = idp->idp_pt;
341 }
b1fca4bf 342 break;
f2412db0 343#ifdef NSIP
f72426ee 344
b1fca4bf
KS
345 case SO_NSIP_ROUTE:
346 error = nsip_route(*value);
f2412db0 347 break;
b1fca4bf 348#endif NSIP
f2412db0
KS
349 default:
350 error = EINVAL;
b1fca4bf
KS
351 }
352 if (value && *value)
353 m_freem(*value);
354 break;
355 }
f72426ee 356 return (error);
b1fca4bf
KS
357}
358
359/*ARGSUSED*/
360idp_usrreq(so, req, m, nam, rights)
361 struct socket *so;
362 int req;
363 struct mbuf *m, *nam, *rights;
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 *)rights));
371 if (rights && rights->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, 2048, 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 }
514release:
515 if (m != NULL)
516 m_freem(m);
517 return (error);
518}
519/*ARGSUSED*/
520idp_raw_usrreq(so, req, m, nam, rights)
521 struct socket *so;
522 int req;
523 struct mbuf *m, *nam, *rights;
524{
525 int error = 0;
526 struct nspcb *nsp = sotonspcb(so);
527 extern struct nspcb nsrawpcb;
528
529 switch (req) {
530
531 case PRU_ATTACH:
532
14bdc762 533 if (!suser() || (nsp != NULL)) {
b1fca4bf
KS
534 error = EINVAL;
535 break;
536 }
537 error = ns_pcballoc(so, &nsrawpcb);
538 if (error)
539 break;
540 error = soreserve(so, 2048, 2048);
541 if (error)
542 break;
543 nsp = sotonspcb(so);
544 nsp->nsp_faddr.x_host = ns_broadhost;
545 nsp->nsp_flags = NSP_RAWIN | NSP_RAWOUT;
546 break;
547 default:
548 error = idp_usrreq(so, req, m, nam, rights);
549 }
f72426ee 550 return (error);
b1fca4bf
KS
551}
552