rip: All processing should only happens in netisr0
[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_ipsec.h"
35 #include "opt_carp.h"
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/jail.h>
41 #include <sys/malloc.h>
42 #include <sys/mbuf.h>
43 #include <sys/proc.h>
44 #include <sys/priv.h>
45 #include <sys/protosw.h>
46 #include <sys/socket.h>
47 #include <sys/socketvar.h>
48 #include <sys/sysctl.h>
49
50 #include <sys/thread2.h>
51 #include <sys/socketvar2.h>
52 #include <sys/msgport2.h>
53
54 #include <machine/stdarg.h>
55
56 #include <net/if.h>
57 #ifdef CARP
58 #include <net/if_types.h>
59 #endif
60 #include <net/route.h>
61
62 #define _IP_VHL
63 #include <netinet/in.h>
64 #include <netinet/in_systm.h>
65 #include <netinet/ip.h>
66 #include <netinet/in_pcb.h>
67 #include <netinet/in_var.h>
68 #include <netinet/ip_var.h>
69
70 #include <net/ip_mroute/ip_mroute.h>
71 #include <net/ipfw/ip_fw.h>
72 #include <net/dummynet/ip_dummynet.h>
73
74 #ifdef FAST_IPSEC
75 #include <netproto/ipsec/ipsec.h>
76 #endif /*FAST_IPSEC*/
77
78 #ifdef IPSEC
79 #include <netinet6/ipsec.h>
80 #endif /*IPSEC*/
81
82 struct  inpcbinfo ripcbinfo;
83 struct  inpcbportinfo ripcbportinfo;
84
85 /* control hooks for ipfw and dummynet */
86 ip_fw_ctl_t *ip_fw_ctl_ptr;
87 ip_dn_ctl_t *ip_dn_ctl_ptr;
88
89 /*
90  * hooks for multicast routing. They all default to NULL,
91  * so leave them not initialized and rely on BSS being set to 0.
92  */
93
94 /* The socket used to communicate with the multicast routing daemon.  */
95 struct socket  *ip_mrouter;
96
97 /* The various mrouter and rsvp functions */
98 int (*ip_mrouter_set)(struct socket *, struct sockopt *);
99 int (*ip_mrouter_get)(struct socket *, struct sockopt *);
100 int (*ip_mrouter_done)(void);
101 int (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *,
102                 struct ip_moptions *);
103 int (*mrt_ioctl)(int, caddr_t);
104 int (*legal_vif_num)(int);
105 u_long (*ip_mcast_src)(int);
106
107 int (*rsvp_input_p)(struct mbuf **, int *, int);
108 int (*ip_rsvp_vif)(struct socket *, struct sockopt *);
109 void (*ip_rsvp_force_done)(struct socket *);
110
111 /*
112  * Nominal space allocated to a raw ip socket.
113  */
114 #define RIPSNDQ         8192
115 #define RIPRCVQ         8192
116
117 /*
118  * Raw interface to IP protocol.
119  */
120
121 /*
122  * Initialize raw connection block queue.
123  */
124 void
125 rip_init(void)
126 {
127         in_pcbinfo_init(&ripcbinfo, 0, FALSE);
128         in_pcbportinfo_init(&ripcbportinfo, 1, FALSE, 0);
129         /*
130          * XXX We don't use the hash list for raw IP, but it's easier
131          * to allocate a one entry hash list than it is to check all
132          * over the place for hashbase == NULL.
133          */
134         ripcbinfo.hashbase = hashinit(1, M_PCB, &ripcbinfo.hashmask);
135         ripcbinfo.portinfo = &ripcbportinfo;
136         ripcbinfo.wildcardhashbase = hashinit(1, M_PCB,
137                                               &ripcbinfo.wildcardhashmask);
138         ripcbinfo.ipi_size = sizeof(struct inpcb);
139 }
140
141 /*
142  * Setup generic address and protocol structures
143  * for raw_input routine, then pass them along with
144  * mbuf chain.
145  */
146 int
147 rip_input(struct mbuf **mp, int *offp, int proto)
148 {
149         struct sockaddr_in ripsrc = { sizeof ripsrc, AF_INET };
150         struct mbuf *m = *mp;
151         struct ip *ip = mtod(m, struct ip *);
152         struct inpcb *inp;
153         struct inpcb *last = NULL;
154         struct mbuf *opts = NULL;
155
156         KASSERT(&curthread->td_msgport == netisr_cpuport(0),
157             ("not in netisr0"));
158
159         *mp = NULL;
160
161         ripsrc.sin_addr = ip->ip_src;
162         LIST_FOREACH(inp, &ripcbinfo.pcblisthead, inp_list) {
163                 if (inp->inp_flags & INP_PLACEMARKER)
164                         continue;
165 #ifdef INET6
166                 if ((inp->inp_vflag & INP_IPV4) == 0)
167                         continue;
168 #endif
169                 if (inp->inp_ip_p && inp->inp_ip_p != proto)
170                         continue;
171                 if (inp->inp_laddr.s_addr != INADDR_ANY &&
172                     inp->inp_laddr.s_addr != ip->ip_dst.s_addr)
173                         continue;
174                 if (inp->inp_faddr.s_addr != INADDR_ANY &&
175                     inp->inp_faddr.s_addr != ip->ip_src.s_addr)
176                         continue;
177                 if (last) {
178                         struct mbuf *n = m_copypacket(m, MB_DONTWAIT);
179
180 #ifdef IPSEC
181                         /* check AH/ESP integrity. */
182                         if (n && ipsec4_in_reject_so(n, last->inp_socket)) {
183                                 m_freem(n);
184                                 ipsecstat.in_polvio++;
185                                 /* do not inject data to pcb */
186                         } else
187 #endif /*IPSEC*/
188 #ifdef FAST_IPSEC
189                         /* check AH/ESP integrity. */
190                         if (ipsec4_in_reject(n, last)) {
191                                 m_freem(n);
192                                 /* do not inject data to pcb */
193                         } else
194 #endif /*FAST_IPSEC*/
195                         if (n) {
196                                 lwkt_gettoken(&last->inp_socket->so_rcv.ssb_token);
197                                 if (last->inp_flags & INP_CONTROLOPTS ||
198                                     last->inp_socket->so_options & SO_TIMESTAMP)
199                                     ip_savecontrol(last, &opts, ip, n);
200                                 if (ssb_appendaddr(&last->inp_socket->so_rcv,
201                                             (struct sockaddr *)&ripsrc, n,
202                                             opts) == 0) {
203                                         /* should notify about lost packet */
204                                         m_freem(n);
205                                         if (opts)
206                                             m_freem(opts);
207                                 } else {
208                                         sorwakeup(last->inp_socket);
209                                 }
210                                 lwkt_reltoken(&last->inp_socket->so_rcv.ssb_token);
211                                 opts = NULL;
212                         }
213                 }
214                 last = inp;
215         }
216 #ifdef IPSEC
217         /* check AH/ESP integrity. */
218         if (last && ipsec4_in_reject_so(m, last->inp_socket)) {
219                 m_freem(m);
220                 ipsecstat.in_polvio++;
221                 ipstat.ips_delivered--;
222                 /* do not inject data to pcb */
223         } else
224 #endif /*IPSEC*/
225 #ifdef FAST_IPSEC
226         /* check AH/ESP integrity. */
227         if (last && ipsec4_in_reject(m, last)) {
228                 m_freem(m);
229                 ipstat.ips_delivered--;
230                 /* do not inject data to pcb */
231         } else
232 #endif /*FAST_IPSEC*/
233         /* Check the minimum TTL for socket. */
234         if (last && ip->ip_ttl < last->inp_ip_minttl) {
235                 m_freem(opts);
236                 ipstat.ips_delivered--;
237         } else if (last) {
238                 if (last->inp_flags & INP_CONTROLOPTS ||
239                     last->inp_socket->so_options & SO_TIMESTAMP)
240                         ip_savecontrol(last, &opts, ip, m);
241                 lwkt_gettoken(&last->inp_socket->so_rcv.ssb_token);
242                 if (ssb_appendaddr(&last->inp_socket->so_rcv,
243                     (struct sockaddr *)&ripsrc, m, opts) == 0) {
244                         m_freem(m);
245                         if (opts)
246                             m_freem(opts);
247                 } else {
248                         sorwakeup(last->inp_socket);
249                 }
250                 lwkt_reltoken(&last->inp_socket->so_rcv.ssb_token);
251         } else {
252                 m_freem(m);
253                 ipstat.ips_noproto++;
254                 ipstat.ips_delivered--;
255         }
256         return(IPPROTO_DONE);
257 }
258
259 /*
260  * Generate IP header and pass packet to ip_output.
261  * Tack on options user may have setup with control call.
262  */
263 int
264 rip_output(struct mbuf *m, struct socket *so, ...)
265 {
266         struct ip *ip;
267         struct inpcb *inp = so->so_pcb;
268         __va_list ap;
269         int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST;
270         u_long dst;
271
272         KASSERT(&curthread->td_msgport == netisr_cpuport(0),
273             ("not in netisr0"));
274
275         __va_start(ap, so);
276         dst = __va_arg(ap, u_long);
277         __va_end(ap);
278
279         /*
280          * If the user handed us a complete IP packet, use it.
281          * Otherwise, allocate an mbuf for a header and fill it in.
282          */
283         if ((inp->inp_flags & INP_HDRINCL) == 0) {
284                 if (m->m_pkthdr.len + sizeof(struct ip) > IP_MAXPACKET) {
285                         m_freem(m);
286                         return(EMSGSIZE);
287                 }
288                 M_PREPEND(m, sizeof(struct ip), MB_WAIT);
289                 if (m == NULL)
290                         return(ENOBUFS);
291                 ip = mtod(m, struct ip *);
292                 ip->ip_tos = inp->inp_ip_tos;
293                 ip->ip_off = 0;
294                 ip->ip_p = inp->inp_ip_p;
295                 ip->ip_len = m->m_pkthdr.len;
296                 ip->ip_src = inp->inp_laddr;
297                 ip->ip_dst.s_addr = dst;
298                 ip->ip_ttl = inp->inp_ip_ttl;
299         } else {
300                 int hlen;
301
302                 if (m->m_pkthdr.len > IP_MAXPACKET) {
303                         m_freem(m);
304                         return(EMSGSIZE);
305                 }
306                 if (m->m_len < sizeof(struct ip)) {
307                         m = m_pullup(m, sizeof(struct ip));
308                         if (m == NULL)
309                                 return ENOBUFS;
310                 }
311                 ip = mtod(m, struct ip *);
312                 hlen = IP_VHL_HL(ip->ip_vhl) << 2;
313
314                 /* Don't allow header length less than the minimum. */
315                 if (hlen < sizeof(struct ip)) {
316                         m_freem(m);
317                         return EINVAL;
318                 }
319
320                 /*
321                  * Don't allow both user specified and setsockopt options.
322                  * Don't allow packet length sizes that will crash.
323                  */
324                 if ((hlen != sizeof(struct ip) && inp->inp_options) ||
325                     ip->ip_len > m->m_pkthdr.len || ip->ip_len < hlen) {
326                         m_freem(m);
327                         return EINVAL;
328                 }
329                 if (ip->ip_id == 0)
330                         ip->ip_id = ip_newid();
331
332                 /* Prevent ip_output from overwriting header fields */
333                 flags |= IP_RAWOUTPUT;
334                 ipstat.ips_rawout++;
335         }
336
337         return ip_output(m, inp->inp_options, &inp->inp_route, flags,
338                          inp->inp_moptions, inp);
339 }
340
341 /*
342  * Raw IP socket option processing.
343  */
344 void
345 rip_ctloutput(netmsg_t msg)
346 {
347         struct socket *so = msg->base.nm_so;
348         struct sockopt *sopt = msg->ctloutput.nm_sopt;
349         struct  inpcb *inp = so->so_pcb;
350         int     error, optval;
351
352         KASSERT(&curthread->td_msgport == netisr_cpuport(0),
353             ("not in netisr0"));
354
355         if (sopt->sopt_level != IPPROTO_IP) {
356                 error = EINVAL;
357                 goto done;
358         }
359
360         error = 0;
361
362         switch (sopt->sopt_dir) {
363         case SOPT_GET:
364                 switch (sopt->sopt_name) {
365                 case IP_HDRINCL:
366                         optval = inp->inp_flags & INP_HDRINCL;
367                         soopt_from_kbuf(sopt, &optval, sizeof optval);
368                         break;
369
370                 case IP_FW_ADD: /* ADD actually returns the body... */
371                 case IP_FW_GET:
372                         if (IPFW_LOADED)
373                                 error = ip_fw_sockopt(sopt);
374                         else
375                                 error = ENOPROTOOPT;
376                         break;
377
378                 case IP_DUMMYNET_GET:
379                         error = ip_dn_sockopt(sopt);
380                         break ;
381
382                 case MRT_INIT:
383                 case MRT_DONE:
384                 case MRT_ADD_VIF:
385                 case MRT_DEL_VIF:
386                 case MRT_ADD_MFC:
387                 case MRT_DEL_MFC:
388                 case MRT_VERSION:
389                 case MRT_ASSERT:
390                 case MRT_API_SUPPORT:
391                 case MRT_API_CONFIG:
392                 case MRT_ADD_BW_UPCALL:
393                 case MRT_DEL_BW_UPCALL:
394                         error = ip_mrouter_get ? ip_mrouter_get(so, sopt) :
395                                 EOPNOTSUPP;
396                         break;
397
398                 default:
399                         ip_ctloutput(msg);
400                         /* msg invalid now */
401                         return;
402                 }
403                 break;
404
405         case SOPT_SET:
406                 switch (sopt->sopt_name) {
407                 case IP_HDRINCL:
408                         error = soopt_to_kbuf(sopt, &optval, sizeof optval,
409                                               sizeof optval);
410                         if (error)
411                                 break;
412                         if (optval)
413                                 inp->inp_flags |= INP_HDRINCL;
414                         else
415                                 inp->inp_flags &= ~INP_HDRINCL;
416                         break;
417
418                 case IP_FW_ADD:
419                 case IP_FW_DEL:
420                 case IP_FW_FLUSH:
421                 case IP_FW_ZERO:
422                 case IP_FW_RESETLOG:
423                         if (IPFW_LOADED)
424                                 error = ip_fw_ctl_ptr(sopt);
425                         else
426                                 error = ENOPROTOOPT;
427                         break;
428
429                 case IP_DUMMYNET_CONFIGURE:
430                 case IP_DUMMYNET_DEL:
431                 case IP_DUMMYNET_FLUSH:
432                         error = ip_dn_sockopt(sopt);
433                         break ;
434
435                 case IP_RSVP_ON:
436                         error = ip_rsvp_init(so);
437                         break;
438
439                 case IP_RSVP_OFF:
440                         error = ip_rsvp_done();
441                         break;
442
443                 case IP_RSVP_VIF_ON:
444                 case IP_RSVP_VIF_OFF:
445                         error = ip_rsvp_vif ?
446                                 ip_rsvp_vif(so, sopt) : EINVAL;
447                         break;
448
449                 case MRT_INIT:
450                 case MRT_DONE:
451                 case MRT_ADD_VIF:
452                 case MRT_DEL_VIF:
453                 case MRT_ADD_MFC:
454                 case MRT_DEL_MFC:
455                 case MRT_VERSION:
456                 case MRT_ASSERT:
457                 case MRT_API_SUPPORT:
458                 case MRT_API_CONFIG:
459                 case MRT_ADD_BW_UPCALL:
460                 case MRT_DEL_BW_UPCALL:
461                         error = ip_mrouter_set ? ip_mrouter_set(so, sopt) :
462                                         EOPNOTSUPP;
463                         break;
464
465                 default:
466                         ip_ctloutput(msg);
467                         /* msg invalid now */
468                         return;
469                 }
470                 break;
471         }
472 done:
473         lwkt_replymsg(&msg->lmsg, error);
474 }
475
476 /*
477  * This function exists solely to receive the PRC_IFDOWN messages which
478  * are sent by if_down().  It looks for an ifaddr whose ifa_addr is sa,
479  * and calls in_ifadown() to remove all routes corresponding to that address.
480  * It also receives the PRC_IFUP messages from if_up() and reinstalls the
481  * interface routes.
482  */
483 void
484 rip_ctlinput(netmsg_t msg)
485 {
486         int cmd = msg->ctlinput.nm_cmd;
487         struct sockaddr *sa = msg->ctlinput.nm_arg;
488         struct in_ifaddr *ia;
489         struct in_ifaddr_container *iac;
490         struct ifnet *ifp;
491         int err;
492         int flags;
493
494         KASSERT(&curthread->td_msgport == netisr_cpuport(0),
495             ("not in netisr0"));
496
497         switch (cmd) {
498         case PRC_IFDOWN:
499                 TAILQ_FOREACH(iac, &in_ifaddrheads[mycpuid], ia_link) {
500                         ia = iac->ia;
501
502                         if (ia->ia_ifa.ifa_addr == sa &&
503                             (ia->ia_flags & IFA_ROUTE)) {
504                                 /*
505                                  * in_ifscrub kills the interface route.
506                                  */
507                                 in_ifscrub(ia->ia_ifp, ia);
508                                 /*
509                                  * in_ifadown gets rid of all the rest of
510                                  * the routes.  This is not quite the right
511                                  * thing to do, but at least if we are running
512                                  * a routing process they will come back.
513                                  */
514                                 in_ifadown(&ia->ia_ifa, 0);
515                                 break;
516                         }
517                 }
518                 break;
519
520         case PRC_IFUP:
521                 ia = NULL;
522                 TAILQ_FOREACH(iac, &in_ifaddrheads[mycpuid], ia_link) {
523                         if (iac->ia->ia_ifa.ifa_addr == sa) {
524                                 ia = iac->ia;
525                                 break;
526                         }
527                 }
528                 if (ia == NULL || (ia->ia_flags & IFA_ROUTE))
529                         goto done;
530                 flags = RTF_UP;
531                 ifp = ia->ia_ifa.ifa_ifp;
532
533 #ifdef CARP
534                 /*
535                  * Don't add prefix routes for CARP interfaces.
536                  * Prefix routes creation is handled by CARP
537                  * interfaces themselves.
538                  */
539                 if (ifp->if_type == IFT_CARP)
540                         goto done;
541 #endif
542
543                 if ((ifp->if_flags & IFF_LOOPBACK) ||
544                     (ifp->if_flags & IFF_POINTOPOINT))
545                         flags |= RTF_HOST;
546
547                 err = rtinit(&ia->ia_ifa, RTM_ADD, flags);
548                 if (err == 0)
549                         ia->ia_flags |= IFA_ROUTE;
550                 break;
551         }
552 done:
553         lwkt_replymsg(&msg->lmsg, 0);
554 }
555
556 u_long  rip_sendspace = RIPSNDQ;
557 u_long  rip_recvspace = RIPRCVQ;
558
559 SYSCTL_INT(_net_inet_raw, OID_AUTO, maxdgram, CTLFLAG_RW,
560     &rip_sendspace, 0, "Maximum outgoing raw IP datagram size");
561 SYSCTL_INT(_net_inet_raw, OID_AUTO, recvspace, CTLFLAG_RW,
562     &rip_recvspace, 0, "Maximum incoming raw IP datagram size");
563
564 static void
565 rip_attach(netmsg_t msg)
566 {
567         struct socket *so = msg->base.nm_so;
568         int proto = msg->attach.nm_proto;
569         struct pru_attach_info *ai = msg->attach.nm_ai;
570         struct inpcb *inp;
571         int error;
572
573         KASSERT(&curthread->td_msgport == netisr_cpuport(0),
574             ("not in netisr0"));
575
576         inp = so->so_pcb;
577         if (inp)
578                 panic("rip_attach");
579         error = priv_check_cred(ai->p_ucred, PRIV_NETINET_RAW, NULL_CRED_OKAY);
580         if (error)
581                 goto done;
582
583         error = soreserve(so, rip_sendspace, rip_recvspace, ai->sb_rlimit);
584         if (error)
585                 goto done;
586
587         error = in_pcballoc(so, &ripcbinfo);
588         if (error == 0) {
589                 inp = (struct inpcb *)so->so_pcb;
590                 inp->inp_vflag |= INP_IPV4;
591                 inp->inp_ip_p = proto;
592                 inp->inp_ip_ttl = ip_defttl;
593         }
594         error = 0;
595 done:
596         lwkt_replymsg(&msg->lmsg, error);
597 }
598
599 static void
600 rip_detach(netmsg_t msg)
601 {
602         struct socket *so = msg->base.nm_so;
603         struct inpcb *inp;
604
605         KASSERT(&curthread->td_msgport == netisr_cpuport(0),
606             ("not in netisr0"));
607
608         inp = so->so_pcb;
609         if (inp == NULL)
610                 panic("rip_detach");
611         if (so == ip_mrouter && ip_mrouter_done)
612                 ip_mrouter_done();
613         if (ip_rsvp_force_done)
614                 ip_rsvp_force_done(so);
615         if (so == ip_rsvpd)
616                 ip_rsvp_done();
617         in_pcbdetach(inp);
618         lwkt_replymsg(&msg->lmsg, 0);
619 }
620
621 static void
622 rip_abort(netmsg_t msg)
623 {
624         /*
625          * Raw socket does not support listen(2),
626          * so this should never be called.
627          */
628         panic("rip_abort is called");
629 }
630
631 static void
632 rip_disconnect(netmsg_t msg)
633 {
634         struct socket *so = msg->base.nm_so;
635         int error;
636
637         KASSERT(&curthread->td_msgport == netisr_cpuport(0),
638             ("not in netisr0"));
639
640         if (so->so_state & SS_ISCONNECTED) {
641                 soisdisconnected(so);
642                 error = 0;
643         } else {
644                 error = ENOTCONN;
645         }
646         lwkt_replymsg(&msg->lmsg, error);
647 }
648
649 static void
650 rip_bind(netmsg_t msg)
651 {
652         struct socket *so = msg->base.nm_so;
653         struct sockaddr *nam = msg->bind.nm_nam;
654         struct inpcb *inp = so->so_pcb;
655         struct sockaddr_in *addr = (struct sockaddr_in *)nam;
656         int error;
657
658         KASSERT(&curthread->td_msgport == netisr_cpuport(0),
659             ("not in netisr0"));
660
661         if (nam->sa_len == sizeof(*addr)) {
662                 if (TAILQ_EMPTY(&ifnet) ||
663                     ((addr->sin_family != AF_INET) &&
664                      (addr->sin_family != AF_IMPLINK)) ||
665                     (addr->sin_addr.s_addr != INADDR_ANY &&
666                      ifa_ifwithaddr((struct sockaddr *)addr) == 0)) {
667                         error = EADDRNOTAVAIL;
668                 } else {
669                         inp->inp_laddr = addr->sin_addr;
670                         error = 0;
671                 }
672         } else {
673                 error = EINVAL;
674         }
675         lwkt_replymsg(&msg->lmsg, error);
676 }
677
678 static void
679 rip_connect(netmsg_t msg)
680 {
681         struct socket *so = msg->base.nm_so;
682         struct sockaddr *nam = msg->connect.nm_nam;
683         struct inpcb *inp = so->so_pcb;
684         struct sockaddr_in *addr = (struct sockaddr_in *)nam;
685         int error;
686
687         KASSERT(&curthread->td_msgport == netisr_cpuport(0),
688             ("not in netisr0"));
689
690         if (nam->sa_len != sizeof(*addr)) {
691                 error = EINVAL;
692         } else if (TAILQ_EMPTY(&ifnet)) {
693                 error = EADDRNOTAVAIL;
694         } else {
695                 if ((addr->sin_family != AF_INET) &&
696                     (addr->sin_family != AF_IMPLINK)) {
697                         error = EAFNOSUPPORT;
698                 } else {
699                         inp->inp_faddr = addr->sin_addr;
700                         soisconnected(so);
701                         error = 0;
702                 }
703         }
704         lwkt_replymsg(&msg->lmsg, error);
705 }
706
707 static void
708 rip_shutdown(netmsg_t msg)
709 {
710         KASSERT(&curthread->td_msgport == netisr_cpuport(0),
711             ("not in netisr0"));
712
713         socantsendmore(msg->base.nm_so);
714         lwkt_replymsg(&msg->lmsg, 0);
715 }
716
717 static void
718 rip_send(netmsg_t msg)
719 {
720         struct socket *so = msg->base.nm_so;
721         struct mbuf *m = msg->send.nm_m;
722         /*struct mbuf *control = msg->send.nm_control;*/
723         struct sockaddr *nam = msg->send.nm_addr;
724         /*int flags = msg->send.nm_flags;*/
725         struct inpcb *inp = so->so_pcb;
726         u_long dst;
727         int error;
728
729         KASSERT(&curthread->td_msgport == netisr_cpuport(0),
730             ("not in netisr0"));
731
732         if (so->so_state & SS_ISCONNECTED) {
733                 if (nam) {
734                         m_freem(m);
735                         error = EISCONN;
736                 } else {
737                         dst = inp->inp_faddr.s_addr;
738                         error = rip_output(m, so, dst);
739                 }
740         } else {
741                 if (nam == NULL) {
742                         m_freem(m);
743                         error = ENOTCONN;
744                 } else {
745                         dst = ((struct sockaddr_in *)nam)->sin_addr.s_addr;
746                         error = rip_output(m, so, dst);
747                 }
748         }
749         lwkt_replymsg(&msg->lmsg, error);
750 }
751
752 SYSCTL_PROC(_net_inet_raw, OID_AUTO/*XXX*/, pcblist, CTLFLAG_RD, &ripcbinfo, 1,
753             in_pcblist_global, "S,xinpcb", "List of active raw IP sockets");
754
755 struct pr_usrreqs rip_usrreqs = {
756         .pru_abort = rip_abort,
757         .pru_accept = pr_generic_notsupp,
758         .pru_attach = rip_attach,
759         .pru_bind = rip_bind,
760         .pru_connect = rip_connect,
761         .pru_connect2 = pr_generic_notsupp,
762         .pru_control = in_control_dispatch,
763         .pru_detach = rip_detach,
764         .pru_disconnect = rip_disconnect,
765         .pru_listen = pr_generic_notsupp,
766         .pru_peeraddr = in_setpeeraddr_dispatch,
767         .pru_rcvd = pr_generic_notsupp,
768         .pru_rcvoob = pr_generic_notsupp,
769         .pru_send = rip_send,
770         .pru_sense = pru_sense_null,
771         .pru_shutdown = rip_shutdown,
772         .pru_sockaddr = in_setsockaddr_dispatch,
773         .pru_sosend = sosend,
774         .pru_soreceive = soreceive
775 };