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