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 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/kernel.h> 43 #include <sys/jail.h> 44 #include <sys/malloc.h> 45 #include <sys/mbuf.h> 46 #include <sys/proc.h> 47 #include <sys/priv.h> 48 #include <sys/protosw.h> 49 #include <sys/socket.h> 50 #include <sys/socketvar.h> 51 #include <sys/sysctl.h> 52 53 #include <sys/thread2.h> 54 #include <sys/socketvar2.h> 55 #include <sys/msgport2.h> 56 57 #include <machine/stdarg.h> 58 59 #include <net/if.h> 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 84 /* control hooks for ipfw and dummynet */ 85 ip_fw_ctl_t *ip_fw_ctl_ptr; 86 ip_dn_ctl_t *ip_dn_ctl_ptr; 87 88 static struct lwkt_token raw_token = LWKT_TOKEN_INITIALIZER(raw_token); 89 90 91 /* 92 * hooks for multicast routing. They all default to NULL, 93 * so leave them not initialized and rely on BSS being set to 0. 94 */ 95 96 /* The socket used to communicate with the multicast routing daemon. */ 97 struct socket *ip_mrouter; 98 99 /* The various mrouter and rsvp functions */ 100 int (*ip_mrouter_set)(struct socket *, struct sockopt *); 101 int (*ip_mrouter_get)(struct socket *, struct sockopt *); 102 int (*ip_mrouter_done)(void); 103 int (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *, 104 struct ip_moptions *); 105 int (*mrt_ioctl)(int, caddr_t); 106 int (*legal_vif_num)(int); 107 u_long (*ip_mcast_src)(int); 108 109 int (*rsvp_input_p)(struct mbuf **, int *, int); 110 int (*ip_rsvp_vif)(struct socket *, struct sockopt *); 111 void (*ip_rsvp_force_done)(struct socket *); 112 113 /* 114 * Nominal space allocated to a raw ip socket. 115 */ 116 #define RIPSNDQ 8192 117 #define RIPRCVQ 8192 118 119 /* 120 * Raw interface to IP protocol. 121 */ 122 123 /* 124 * Initialize raw connection block queue. 125 */ 126 void 127 rip_init(void) 128 { 129 in_pcbinfo_init(&ripcbinfo); 130 /* 131 * XXX We don't use the hash list for raw IP, but it's easier 132 * to allocate a one entry hash list than it is to check all 133 * over the place for hashbase == NULL. 134 */ 135 ripcbinfo.hashbase = hashinit(1, M_PCB, &ripcbinfo.hashmask); 136 ripcbinfo.porthashbase = hashinit(1, M_PCB, &ripcbinfo.porthashmask); 137 ripcbinfo.wildcardhashbase = hashinit(1, M_PCB, 138 &ripcbinfo.wildcardhashmask); 139 ripcbinfo.ipi_size = sizeof(struct inpcb); 140 } 141 142 /* 143 * Setup generic address and protocol structures 144 * for raw_input routine, then pass them along with 145 * mbuf chain. 146 */ 147 int 148 rip_input(struct mbuf **mp, int *offp, int proto) 149 { 150 struct sockaddr_in ripsrc = { sizeof ripsrc, AF_INET }; 151 struct mbuf *m = *mp; 152 struct ip *ip = mtod(m, struct ip *); 153 struct inpcb *inp; 154 struct inpcb *last = NULL; 155 struct mbuf *opts = NULL; 156 int off; 157 158 off = *offp; 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 if ((ifp->if_flags & IFF_LOOPBACK) || 527 (ifp->if_flags & IFF_POINTOPOINT)) 528 flags |= RTF_HOST; 529 530 err = rtinit(&ia->ia_ifa, RTM_ADD, flags); 531 if (err == 0) 532 ia->ia_flags |= IFA_ROUTE; 533 break; 534 } 535 done: 536 lwkt_replymsg(&msg->lmsg, 0); 537 } 538 539 u_long rip_sendspace = RIPSNDQ; 540 u_long rip_recvspace = RIPRCVQ; 541 542 SYSCTL_INT(_net_inet_raw, OID_AUTO, maxdgram, CTLFLAG_RW, 543 &rip_sendspace, 0, "Maximum outgoing raw IP datagram size"); 544 SYSCTL_INT(_net_inet_raw, OID_AUTO, recvspace, CTLFLAG_RW, 545 &rip_recvspace, 0, "Maximum incoming raw IP datagram size"); 546 547 static void 548 rip_attach(netmsg_t msg) 549 { 550 struct socket *so = msg->base.nm_so; 551 int proto = msg->attach.nm_proto; 552 struct pru_attach_info *ai = msg->attach.nm_ai; 553 struct inpcb *inp; 554 int error; 555 556 inp = so->so_pcb; 557 if (inp) 558 panic("rip_attach"); 559 error = priv_check_cred(ai->p_ucred, PRIV_NETINET_RAW, NULL_CRED_OKAY); 560 if (error) 561 goto done; 562 563 error = soreserve(so, rip_sendspace, rip_recvspace, ai->sb_rlimit); 564 if (error) 565 goto done; 566 567 lwkt_gettoken(&raw_token); 568 error = in_pcballoc(so, &ripcbinfo); 569 if (error == 0) { 570 inp = (struct inpcb *)so->so_pcb; 571 inp->inp_vflag |= INP_IPV4; 572 inp->inp_ip_p = proto; 573 inp->inp_ip_ttl = ip_defttl; 574 } 575 lwkt_reltoken(&raw_token); 576 error = 0; 577 done: 578 lwkt_replymsg(&msg->lmsg, error); 579 } 580 581 static void 582 rip_detach(netmsg_t msg) 583 { 584 struct socket *so = msg->base.nm_so; 585 struct inpcb *inp; 586 587 inp = so->so_pcb; 588 if (inp == NULL) 589 panic("rip_detach"); 590 if (so == ip_mrouter && ip_mrouter_done) 591 ip_mrouter_done(); 592 if (ip_rsvp_force_done) 593 ip_rsvp_force_done(so); 594 if (so == ip_rsvpd) 595 ip_rsvp_done(); 596 in_pcbdetach(inp); 597 lwkt_replymsg(&msg->lmsg, 0); 598 } 599 600 /* 601 * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort() 602 * will sofree() it when we return. 603 */ 604 static void 605 rip_abort(netmsg_t msg) 606 { 607 struct socket *so = msg->base.nm_so; 608 int error; 609 610 soisdisconnected(so); 611 if (so->so_state & SS_NOFDREF) { /* XXX not sure why this test */ 612 rip_detach(msg); 613 /* msg invalid now */ 614 return; 615 } 616 error = 0; 617 lwkt_replymsg(&msg->lmsg, error); 618 } 619 620 static void 621 rip_disconnect(netmsg_t msg) 622 { 623 struct socket *so = msg->base.nm_so; 624 int error; 625 626 if (so->so_state & SS_ISCONNECTED) { 627 soreference(so); 628 rip_abort(msg); 629 /* msg invalid now */ 630 sofree(so); 631 return; 632 } 633 error = ENOTCONN; 634 lwkt_replymsg(&msg->lmsg, error); 635 } 636 637 static void 638 rip_bind(netmsg_t msg) 639 { 640 struct socket *so = msg->base.nm_so; 641 struct sockaddr *nam = msg->bind.nm_nam; 642 struct inpcb *inp = so->so_pcb; 643 struct sockaddr_in *addr = (struct sockaddr_in *)nam; 644 int error; 645 646 if (nam->sa_len == sizeof(*addr)) { 647 if (TAILQ_EMPTY(&ifnet) || 648 ((addr->sin_family != AF_INET) && 649 (addr->sin_family != AF_IMPLINK)) || 650 (addr->sin_addr.s_addr != INADDR_ANY && 651 ifa_ifwithaddr((struct sockaddr *)addr) == 0)) { 652 error = EADDRNOTAVAIL; 653 } else { 654 inp->inp_laddr = addr->sin_addr; 655 error = 0; 656 } 657 } else { 658 error = EINVAL; 659 } 660 lwkt_replymsg(&msg->lmsg, error); 661 } 662 663 static void 664 rip_connect(netmsg_t msg) 665 { 666 struct socket *so = msg->base.nm_so; 667 struct sockaddr *nam = msg->connect.nm_nam; 668 struct inpcb *inp = so->so_pcb; 669 struct sockaddr_in *addr = (struct sockaddr_in *)nam; 670 int error; 671 672 if (nam->sa_len != sizeof(*addr)) { 673 error = EINVAL; 674 } else if (TAILQ_EMPTY(&ifnet)) { 675 error = EADDRNOTAVAIL; 676 } else { 677 if ((addr->sin_family != AF_INET) && 678 (addr->sin_family != AF_IMPLINK)) { 679 error = EAFNOSUPPORT; 680 } else { 681 inp->inp_faddr = addr->sin_addr; 682 soisconnected(so); 683 error = 0; 684 } 685 } 686 lwkt_replymsg(&msg->lmsg, error); 687 } 688 689 static void 690 rip_shutdown(netmsg_t msg) 691 { 692 socantsendmore(msg->base.nm_so); 693 lwkt_replymsg(&msg->lmsg, 0); 694 } 695 696 static void 697 rip_send(netmsg_t msg) 698 { 699 struct socket *so = msg->base.nm_so; 700 struct mbuf *m = msg->send.nm_m; 701 /*struct mbuf *control = msg->send.nm_control;*/ 702 struct sockaddr *nam = msg->send.nm_addr; 703 /*int flags = msg->send.nm_flags;*/ 704 struct inpcb *inp = so->so_pcb; 705 u_long dst; 706 int error; 707 708 if (so->so_state & SS_ISCONNECTED) { 709 if (nam) { 710 m_freem(m); 711 error = EISCONN; 712 } else { 713 dst = inp->inp_faddr.s_addr; 714 error = rip_output(m, so, dst); 715 } 716 } else { 717 if (nam == NULL) { 718 m_freem(m); 719 error = ENOTCONN; 720 } else { 721 dst = ((struct sockaddr_in *)nam)->sin_addr.s_addr; 722 error = rip_output(m, so, dst); 723 } 724 } 725 lwkt_replymsg(&msg->lmsg, error); 726 } 727 728 SYSCTL_PROC(_net_inet_raw, OID_AUTO/*XXX*/, pcblist, CTLFLAG_RD, &ripcbinfo, 0, 729 in_pcblist_global, "S,xinpcb", "List of active raw IP sockets"); 730 731 struct pr_usrreqs rip_usrreqs = { 732 .pru_abort = rip_abort, 733 .pru_accept = pr_generic_notsupp, 734 .pru_attach = rip_attach, 735 .pru_bind = rip_bind, 736 .pru_connect = rip_connect, 737 .pru_connect2 = pr_generic_notsupp, 738 .pru_control = in_control_dispatch, 739 .pru_detach = rip_detach, 740 .pru_disconnect = rip_disconnect, 741 .pru_listen = pr_generic_notsupp, 742 .pru_peeraddr = in_setpeeraddr_dispatch, 743 .pru_rcvd = pr_generic_notsupp, 744 .pru_rcvoob = pr_generic_notsupp, 745 .pru_send = rip_send, 746 .pru_sense = pru_sense_null, 747 .pru_shutdown = rip_shutdown, 748 .pru_sockaddr = in_setsockaddr_dispatch, 749 .pru_sosend = sosend, 750 .pru_soreceive = soreceive 751 }; 752