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