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