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