nrelease - fix/improve livecd
[dragonfly.git] / sys / netinet / raw_ip.c
1 /*
2  * Copyright (c) 1982, 1986, 1988, 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. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  *      @(#)raw_ip.c    8.7 (Berkeley) 5/15/95
30  * $FreeBSD: src/sys/netinet/raw_ip.c,v 1.64.2.16 2003/08/24 08:24:38 hsu Exp $
31  */
32
33 #include "opt_inet6.h"
34 #include "opt_carp.h"
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/jail.h>
40 #include <sys/malloc.h>
41 #include <sys/mbuf.h>
42 #include <sys/proc.h>
43 #include <sys/caps.h>
44 #include <sys/protosw.h>
45 #include <sys/socket.h>
46 #include <sys/socketvar.h>
47 #include <sys/sysctl.h>
48
49 #include <sys/socketvar2.h>
50 #include <sys/msgport2.h>
51
52 #include <machine/stdarg.h>
53
54 #include <net/if.h>
55 #ifdef CARP
56 #include <net/if_types.h>
57 #endif
58 #include <net/route.h>
59
60 #define _IP_VHL
61 #include <netinet/in.h>
62 #include <netinet/in_systm.h>
63 #include <netinet/ip.h>
64 #include <netinet/in_pcb.h>
65 #include <netinet/in_var.h>
66 #include <netinet/ip_var.h>
67
68 #include <net/ip_mroute/ip_mroute.h>
69 #include <net/ipfw/ip_fw.h>
70 #include <net/ipfw3/ip_fw.h>
71 #include <net/dummynet/ip_dummynet.h>
72 #include <net/dummynet3/ip_dummynet3.h>
73
74 struct  inpcbinfo ripcbinfo;
75 struct  inpcbportinfo ripcbportinfo;
76
77 /*
78  * hooks for multicast routing. They all default to NULL,
79  * so leave them not initialized and rely on BSS being set to 0.
80  */
81
82 /* The socket used to communicate with the multicast routing daemon.  */
83 struct socket  *ip_mrouter;
84
85 /* The various mrouter and rsvp functions */
86 int (*ip_mrouter_set)(struct socket *, struct sockopt *);
87 int (*ip_mrouter_get)(struct socket *, struct sockopt *);
88 int (*ip_mrouter_done)(void);
89 int (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *,
90                 struct ip_moptions *);
91 int (*mrt_ioctl)(u_long, caddr_t);
92 int (*legal_vif_num)(int);
93 u_long (*ip_mcast_src)(int);
94
95 int (*rsvp_input_p)(struct mbuf **, int *, int);
96 int (*ip_rsvp_vif)(struct socket *, struct sockopt *);
97 void (*ip_rsvp_force_done)(struct socket *);
98
99 /*
100  * Nominal space allocated to a raw ip socket.
101  */
102 #define RIPSNDQ         8192
103 #define RIPRCVQ         8192
104
105 /*
106  * Raw interface to IP protocol.
107  */
108
109 /*
110  * Initialize raw connection block queue.
111  */
112 void
113 rip_init(void)
114 {
115         in_pcbinfo_init(&ripcbinfo, 0, FALSE);
116         in_pcbportinfo_init(&ripcbportinfo, 1, 0);
117         /*
118          * XXX We don't use the hash list for raw IP, but it's easier
119          * to allocate a one entry hash list than it is to check all
120          * over the place for hashbase == NULL.
121          */
122         ripcbinfo.hashbase = hashinit(1, M_PCB, &ripcbinfo.hashmask);
123         in_pcbportinfo_set(&ripcbinfo, &ripcbportinfo, 1);
124         ripcbinfo.wildcardhashbase = hashinit(1, M_PCB,
125                                               &ripcbinfo.wildcardhashmask);
126         ripcbinfo.ipi_size = sizeof(struct inpcb);
127 }
128
129 /*
130  * Setup generic address and protocol structures
131  * for raw_input routine, then pass them along with
132  * mbuf chain.
133  */
134 int
135 rip_input(struct mbuf **mp, int *offp, int proto)
136 {
137         struct sockaddr_in ripsrc = { sizeof ripsrc, AF_INET };
138         struct mbuf *m = *mp;
139         struct ip *ip = mtod(m, struct ip *);
140         struct inpcb *inp;
141         struct inpcb *last = NULL;
142         struct mbuf *opts = NULL;
143
144         ASSERT_NETISR0;
145
146         *mp = NULL;
147
148         ripsrc.sin_addr = ip->ip_src;
149         LIST_FOREACH(inp, &ripcbinfo.pcblisthead, inp_list) {
150                 if (inp->inp_flags & INP_PLACEMARKER)
151                         continue;
152 #ifdef INET6
153                 if (!INP_ISIPV4(inp))
154                         continue;
155 #endif
156                 if (inp->inp_ip_p && inp->inp_ip_p != proto)
157                         continue;
158                 if (inp->inp_laddr.s_addr != INADDR_ANY &&
159                     inp->inp_laddr.s_addr != ip->ip_dst.s_addr)
160                         continue;
161                 if (inp->inp_faddr.s_addr != INADDR_ANY &&
162                     inp->inp_faddr.s_addr != ip->ip_src.s_addr)
163                         continue;
164                 if (last) {
165                         struct mbuf *n = m_copypacket(m, M_NOWAIT);
166
167                         if (n) {
168                                 lwkt_gettoken(&last->inp_socket->so_rcv.ssb_token);
169                                 if (last->inp_flags & INP_CONTROLOPTS ||
170                                     last->inp_socket->so_options & SO_TIMESTAMP)
171                                     ip_savecontrol(last, &opts, ip, n);
172                                 if (ssb_appendaddr(&last->inp_socket->so_rcv,
173                                             (struct sockaddr *)&ripsrc, n,
174                                             opts) == 0) {
175                                         m_freem(n);
176                                         if (opts)
177                                             m_freem(opts);
178                                         soroverflow(last->inp_socket);
179                                 } else {
180                                         sorwakeup(last->inp_socket);
181                                 }
182                                 lwkt_reltoken(&last->inp_socket->so_rcv.ssb_token);
183                                 opts = NULL;
184                         }
185                 }
186                 last = inp;
187         }
188         /* Check the minimum TTL for socket. */
189         if (last && ip->ip_ttl < last->inp_ip_minttl) {
190                 m_freem(opts);
191                 ipstat.ips_delivered--;
192         } else if (last) {
193                 if (last->inp_flags & INP_CONTROLOPTS ||
194                     last->inp_socket->so_options & SO_TIMESTAMP)
195                         ip_savecontrol(last, &opts, ip, m);
196                 lwkt_gettoken(&last->inp_socket->so_rcv.ssb_token);
197                 if (ssb_appendaddr(&last->inp_socket->so_rcv,
198                     (struct sockaddr *)&ripsrc, m, opts) == 0) {
199                         m_freem(m);
200                         if (opts)
201                             m_freem(opts);
202                         soroverflow(last->inp_socket);
203                 } else {
204                         sorwakeup(last->inp_socket);
205                 }
206                 lwkt_reltoken(&last->inp_socket->so_rcv.ssb_token);
207         } else {
208                 m_freem(m);
209                 ipstat.ips_noproto++;
210                 ipstat.ips_delivered--;
211         }
212         return(IPPROTO_DONE);
213 }
214
215 /*
216  * Generate IP header and pass packet to ip_output.
217  * Tack on options user may have setup with control call.
218  */
219 int
220 rip_output(struct mbuf *m, struct socket *so, ...)
221 {
222         struct ip *ip;
223         struct inpcb *inp = so->so_pcb;
224         __va_list ap;
225         int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST;
226         u_long dst;
227
228         ASSERT_NETISR0;
229
230         __va_start(ap, so);
231         dst = __va_arg(ap, u_long);
232         __va_end(ap);
233
234         /*
235          * If the user handed us a complete IP packet, use it.
236          * Otherwise, allocate an mbuf for a header and fill it in.
237          */
238         if ((inp->inp_flags & INP_HDRINCL) == 0) {
239                 if (m->m_pkthdr.len + sizeof(struct ip) > IP_MAXPACKET) {
240                         m_freem(m);
241                         return(EMSGSIZE);
242                 }
243                 M_PREPEND(m, sizeof(struct ip), M_WAITOK);
244                 ip = mtod(m, struct ip *);
245                 ip->ip_tos = inp->inp_ip_tos;
246                 ip->ip_off = 0;
247                 ip->ip_p = inp->inp_ip_p;
248                 ip->ip_len = htons(m->m_pkthdr.len); /* incls header now */
249                 ip->ip_src = inp->inp_laddr;
250                 ip->ip_dst.s_addr = dst;
251                 ip->ip_ttl = inp->inp_ip_ttl;
252         } else {
253                 int hlen;
254                 int ip_len;
255
256                 if (m->m_pkthdr.len > IP_MAXPACKET) {
257                         m_freem(m);
258                         return(EMSGSIZE);
259                 }
260                 if (m->m_len < sizeof(struct ip)) {
261                         m = m_pullup(m, sizeof(struct ip));
262                         if (m == NULL)
263                                 return ENOBUFS;
264                 }
265                 ip = mtod(m, struct ip *);
266                 hlen = IP_VHL_HL(ip->ip_vhl) << 2;
267                 ip_len = ntohs(ip->ip_len);     /* includes header */
268
269                 /*
270                  * Don't allow both user specified and setsockopt options.
271                  * Don't allow packet length sizes that will crash.
272                  */
273                 if (hlen < sizeof(struct ip) ||
274                     (hlen != sizeof(struct ip) && inp->inp_options) ||
275                     ip_len > m->m_pkthdr.len ||
276                     ip_len < hlen)
277                 {
278                         m_freem(m);
279                         return EINVAL;
280                 }
281
282                 /*
283                  * System supplies ip_id if passed as 0.
284                  */
285                 if (ip->ip_id == 0)
286                         ip->ip_id = ip_newid();
287
288                 /* Prevent ip_output from overwriting header fields */
289                 flags |= IP_RAWOUTPUT;
290                 ipstat.ips_rawout++;
291         }
292
293         return ip_output(m, inp->inp_options, &inp->inp_route, flags,
294                          inp->inp_moptions, inp);
295 }
296
297 /*
298  * Raw IP socket option processing.
299  */
300 void
301 rip_ctloutput(netmsg_t msg)
302 {
303         struct socket *so = msg->base.nm_so;
304         struct sockopt *sopt = msg->ctloutput.nm_sopt;
305         struct  inpcb *inp = so->so_pcb;
306         int     error, optval;
307
308         ASSERT_NETISR0;
309
310         error = 0;
311
312         /* Get socket's owner cpuid hint */
313         if (sopt->sopt_level == SOL_SOCKET &&
314             sopt->sopt_dir == SOPT_GET &&
315             sopt->sopt_name == SO_CPUHINT) {
316                 optval = mycpuid;
317                 soopt_from_kbuf(sopt, &optval, sizeof(optval));
318                 goto done;
319         }
320
321         if (sopt->sopt_level != IPPROTO_IP) {
322                 error = EINVAL;
323                 goto done;
324         }
325
326         switch (sopt->sopt_dir) {
327         case SOPT_GET:
328                 switch (sopt->sopt_name) {
329                 case IP_HDRINCL:
330                         optval = inp->inp_flags & INP_HDRINCL;
331                         soopt_from_kbuf(sopt, &optval, sizeof optval);
332                         break;
333
334                 case IP_FW_X:
335                         error = ip_fw3_sockopt(sopt);
336                         break;
337
338                 case IP_FW_ADD: /* ADD actually returns the body... */
339                 case IP_FW_GET:
340                 case IP_FW_TBL_GET:
341                 case IP_FW_TBL_EXPIRE: /* returns # of expired addresses */
342                         error = ip_fw_sockopt(sopt);
343                         break;
344
345                 case IP_DUMMYNET_GET:
346                         error = ip_dn_sockopt(sopt);
347                         break ;
348
349                 case MRT_INIT:
350                 case MRT_DONE:
351                 case MRT_ADD_VIF:
352                 case MRT_DEL_VIF:
353                 case MRT_ADD_MFC:
354                 case MRT_DEL_MFC:
355                 case MRT_VERSION:
356                 case MRT_ASSERT:
357                 case MRT_API_SUPPORT:
358                 case MRT_API_CONFIG:
359                 case MRT_ADD_BW_UPCALL:
360                 case MRT_DEL_BW_UPCALL:
361                         error = ip_mrouter_get ? ip_mrouter_get(so, sopt) :
362                                 EOPNOTSUPP;
363                         break;
364
365                 default:
366                         ip_ctloutput(msg);
367                         /* msg invalid now */
368                         return;
369                 }
370                 break;
371
372         case SOPT_SET:
373                 switch (sopt->sopt_name) {
374                 case IP_HDRINCL:
375                         error = soopt_to_kbuf(sopt, &optval, sizeof optval,
376                                               sizeof optval);
377                         if (error)
378                                 break;
379                         if (optval)
380                                 inp->inp_flags |= INP_HDRINCL;
381                         else
382                                 inp->inp_flags &= ~INP_HDRINCL;
383                         break;
384
385                 case IP_FW_X:
386                         error = ip_fw3_sockopt(sopt);
387                         break;
388
389                 case IP_FW_ADD:
390                 case IP_FW_DEL:
391                 case IP_FW_FLUSH:
392                 case IP_FW_ZERO:
393                 case IP_FW_RESETLOG:
394                 case IP_FW_TBL_CREATE:
395                 case IP_FW_TBL_DESTROY:
396                 case IP_FW_TBL_ADD:
397                 case IP_FW_TBL_DEL:
398                 case IP_FW_TBL_FLUSH:
399                 case IP_FW_TBL_ZERO:
400                 case IP_FW_TBL_EXPIRE:
401                         error = ip_fw_sockopt(sopt);
402                         break;
403
404                 case IP_DUMMYNET_CONFIGURE:
405                 case IP_DUMMYNET_DEL:
406                 case IP_DUMMYNET_FLUSH:
407                         error = ip_dn_sockopt(sopt);
408                         break;
409
410                 case IP_RSVP_ON:
411                         error = ip_rsvp_init(so);
412                         break;
413
414                 case IP_RSVP_OFF:
415                         error = ip_rsvp_done();
416                         break;
417
418                 case IP_RSVP_VIF_ON:
419                 case IP_RSVP_VIF_OFF:
420                         error = ip_rsvp_vif ?
421                                 ip_rsvp_vif(so, sopt) : EINVAL;
422                         break;
423
424                 case MRT_INIT:
425                 case MRT_DONE:
426                 case MRT_ADD_VIF:
427                 case MRT_DEL_VIF:
428                 case MRT_ADD_MFC:
429                 case MRT_DEL_MFC:
430                 case MRT_VERSION:
431                 case MRT_ASSERT:
432                 case MRT_API_SUPPORT:
433                 case MRT_API_CONFIG:
434                 case MRT_ADD_BW_UPCALL:
435                 case MRT_DEL_BW_UPCALL:
436                         error = ip_mrouter_set ? ip_mrouter_set(so, sopt) :
437                                         EOPNOTSUPP;
438                         break;
439
440                 default:
441                         ip_ctloutput(msg);
442                         /* msg invalid now */
443                         return;
444                 }
445                 break;
446         }
447 done:
448         lwkt_replymsg(&msg->lmsg, error);
449 }
450
451 u_long  rip_sendspace = RIPSNDQ;
452 u_long  rip_recvspace = RIPRCVQ;
453
454 SYSCTL_INT(_net_inet_raw, OID_AUTO, maxdgram, CTLFLAG_RW,
455     &rip_sendspace, 0, "Maximum outgoing raw IP datagram size");
456 SYSCTL_INT(_net_inet_raw, OID_AUTO, recvspace, CTLFLAG_RW,
457     &rip_recvspace, 0, "Maximum incoming raw IP datagram size");
458
459 static void
460 rip_attach(netmsg_t msg)
461 {
462         struct socket *so = msg->base.nm_so;
463         int proto = msg->attach.nm_proto;
464         struct pru_attach_info *ai = msg->attach.nm_ai;
465         struct inpcb *inp;
466         int error;
467
468         ASSERT_NETISR0;
469
470         inp = so->so_pcb;
471         if (inp)
472                 panic("rip_attach");
473         error = caps_priv_check(ai->p_ucred, SYSCAP_NONET_RAW |
474                                              __SYSCAP_NULLCRED);
475         if (error)
476                 goto done;
477
478         error = soreserve(so, rip_sendspace, rip_recvspace, ai->sb_rlimit);
479         if (error)
480                 goto done;
481
482         error = in_pcballoc(so, &ripcbinfo);
483         if (error == 0) {
484                 inp = (struct inpcb *)so->so_pcb;
485                 inp->inp_ip_p = proto;
486                 inp->inp_ip_ttl = ip_defttl;
487         }
488 done:
489         lwkt_replymsg(&msg->lmsg, error);
490 }
491
492 static void
493 rip_detach(netmsg_t msg)
494 {
495         struct socket *so = msg->base.nm_so;
496         struct inpcb *inp;
497
498         ASSERT_NETISR0;
499
500         inp = so->so_pcb;
501         if (inp == NULL)
502                 panic("rip_detach");
503         if (so == ip_mrouter && ip_mrouter_done)
504                 ip_mrouter_done();
505         if (ip_rsvp_force_done)
506                 ip_rsvp_force_done(so);
507         if (so == ip_rsvpd)
508                 ip_rsvp_done();
509         in_pcbdetach(inp);
510         lwkt_replymsg(&msg->lmsg, 0);
511 }
512
513 static void
514 rip_abort(netmsg_t msg)
515 {
516         /*
517          * Raw socket does not support listen(2),
518          * so this should never be called.
519          */
520         panic("rip_abort is called");
521 }
522
523 static void
524 rip_disconnect(netmsg_t msg)
525 {
526         struct socket *so = msg->base.nm_so;
527         int error;
528
529         ASSERT_NETISR0;
530
531         if (so->so_state & SS_ISCONNECTED) {
532                 soisdisconnected(so);
533                 error = 0;
534         } else {
535                 error = ENOTCONN;
536         }
537         lwkt_replymsg(&msg->lmsg, error);
538 }
539
540 static void
541 rip_bind(netmsg_t msg)
542 {
543         struct socket *so = msg->base.nm_so;
544         struct sockaddr *nam = msg->bind.nm_nam;
545         struct inpcb *inp = so->so_pcb;
546         struct sockaddr_in *addr = (struct sockaddr_in *)nam;
547         int error;
548
549         ASSERT_NETISR0;
550
551         if (nam->sa_len == sizeof(*addr)) {
552                 if (ifnet_array_isempty() ||
553                     ((addr->sin_family != AF_INET) &&
554                      (addr->sin_family != AF_IMPLINK)) ||
555                     (addr->sin_addr.s_addr != INADDR_ANY &&
556                      ifa_ifwithaddr((struct sockaddr *)addr) == 0)) {
557                         error = EADDRNOTAVAIL;
558                 } else {
559                         inp->inp_laddr = addr->sin_addr;
560                         error = 0;
561                 }
562         } else {
563                 error = EINVAL;
564         }
565         lwkt_replymsg(&msg->lmsg, error);
566 }
567
568 static void
569 rip_connect(netmsg_t msg)
570 {
571         struct socket *so = msg->base.nm_so;
572         struct sockaddr *nam = msg->connect.nm_nam;
573         struct inpcb *inp = so->so_pcb;
574         struct sockaddr_in *addr = (struct sockaddr_in *)nam;
575         int error;
576
577         ASSERT_NETISR0;
578
579         if (nam->sa_len != sizeof(*addr)) {
580                 error = EINVAL;
581         } else if (ifnet_array_isempty()) {
582                 error = EADDRNOTAVAIL;
583         } else {
584                 if ((addr->sin_family != AF_INET) &&
585                     (addr->sin_family != AF_IMPLINK)) {
586                         error = EAFNOSUPPORT;
587                 } else {
588                         inp->inp_faddr = addr->sin_addr;
589                         soisconnected(so);
590                         error = 0;
591                 }
592         }
593         lwkt_replymsg(&msg->lmsg, error);
594 }
595
596 static void
597 rip_shutdown(netmsg_t msg)
598 {
599         ASSERT_NETISR0;
600
601         socantsendmore(msg->base.nm_so);
602         lwkt_replymsg(&msg->lmsg, 0);
603 }
604
605 static void
606 rip_send(netmsg_t msg)
607 {
608         struct socket *so = msg->base.nm_so;
609         struct mbuf *m = msg->send.nm_m;
610         /*struct mbuf *control = msg->send.nm_control;*/
611         struct sockaddr *nam = msg->send.nm_addr;
612         /*int flags = msg->send.nm_flags;*/
613         struct inpcb *inp = so->so_pcb;
614         u_long dst;
615         int error;
616
617         ASSERT_NETISR0;
618
619         if (so->so_state & SS_ISCONNECTED) {
620                 if (nam) {
621                         m_freem(m);
622                         error = EISCONN;
623                 } else {
624                         dst = inp->inp_faddr.s_addr;
625                         error = rip_output(m, so, dst);
626                 }
627         } else {
628                 if (nam == NULL) {
629                         m_freem(m);
630                         error = ENOTCONN;
631                 } else {
632                         dst = ((struct sockaddr_in *)nam)->sin_addr.s_addr;
633                         error = rip_output(m, so, dst);
634                 }
635         }
636         lwkt_replymsg(&msg->lmsg, error);
637 }
638
639 SYSCTL_PROC(_net_inet_raw, OID_AUTO/*XXX*/, pcblist, CTLFLAG_RD, &ripcbinfo, 1,
640             in_pcblist_range, "S,xinpcb", "List of active raw IP sockets");
641
642 struct pr_usrreqs rip_usrreqs = {
643         .pru_abort = rip_abort,
644         .pru_accept = pr_generic_notsupp,
645         .pru_attach = rip_attach,
646         .pru_bind = rip_bind,
647         .pru_connect = rip_connect,
648         .pru_connect2 = pr_generic_notsupp,
649         .pru_control = in_control_dispatch,
650         .pru_detach = rip_detach,
651         .pru_disconnect = rip_disconnect,
652         .pru_listen = pr_generic_notsupp,
653         .pru_peeraddr = in_setpeeraddr_dispatch,
654         .pru_rcvd = pr_generic_notsupp,
655         .pru_rcvoob = pr_generic_notsupp,
656         .pru_send = rip_send,
657         .pru_sense = pru_sense_null,
658         .pru_shutdown = rip_shutdown,
659         .pru_sockaddr = in_setsockaddr_dispatch,
660         .pru_sosend = sosend,
661         .pru_soreceive = soreceive
662 };