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