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