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