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 int off; 161 162 off = *offp; 163 *mp = NULL; 164 165 ripsrc.sin_addr = ip->ip_src; 166 lwkt_gettoken(&raw_token); 167 LIST_FOREACH(inp, &ripcbinfo.pcblisthead, inp_list) { 168 if (inp->inp_flags & INP_PLACEMARKER) 169 continue; 170 #ifdef INET6 171 if ((inp->inp_vflag & INP_IPV4) == 0) 172 continue; 173 #endif 174 if (inp->inp_ip_p && inp->inp_ip_p != proto) 175 continue; 176 if (inp->inp_laddr.s_addr != INADDR_ANY && 177 inp->inp_laddr.s_addr != ip->ip_dst.s_addr) 178 continue; 179 if (inp->inp_faddr.s_addr != INADDR_ANY && 180 inp->inp_faddr.s_addr != ip->ip_src.s_addr) 181 continue; 182 if (last) { 183 struct mbuf *n = m_copypacket(m, MB_DONTWAIT); 184 185 #ifdef IPSEC 186 /* check AH/ESP integrity. */ 187 if (n && ipsec4_in_reject_so(n, last->inp_socket)) { 188 m_freem(n); 189 ipsecstat.in_polvio++; 190 /* do not inject data to pcb */ 191 } else 192 #endif /*IPSEC*/ 193 #ifdef FAST_IPSEC 194 /* check AH/ESP integrity. */ 195 if (ipsec4_in_reject(n, last)) { 196 m_freem(n); 197 /* do not inject data to pcb */ 198 } else 199 #endif /*FAST_IPSEC*/ 200 if (n) { 201 lwkt_gettoken(&last->inp_socket->so_rcv.ssb_token); 202 if (last->inp_flags & INP_CONTROLOPTS || 203 last->inp_socket->so_options & SO_TIMESTAMP) 204 ip_savecontrol(last, &opts, ip, n); 205 if (ssb_appendaddr(&last->inp_socket->so_rcv, 206 (struct sockaddr *)&ripsrc, n, 207 opts) == 0) { 208 /* should notify about lost packet */ 209 m_freem(n); 210 if (opts) 211 m_freem(opts); 212 } else { 213 sorwakeup(last->inp_socket); 214 } 215 lwkt_reltoken(&last->inp_socket->so_rcv.ssb_token); 216 opts = NULL; 217 } 218 } 219 last = inp; 220 } 221 #ifdef IPSEC 222 /* check AH/ESP integrity. */ 223 if (last && ipsec4_in_reject_so(m, last->inp_socket)) { 224 m_freem(m); 225 ipsecstat.in_polvio++; 226 ipstat.ips_delivered--; 227 /* do not inject data to pcb */ 228 } else 229 #endif /*IPSEC*/ 230 #ifdef FAST_IPSEC 231 /* check AH/ESP integrity. */ 232 if (last && ipsec4_in_reject(m, last)) { 233 m_freem(m); 234 ipstat.ips_delivered--; 235 /* do not inject data to pcb */ 236 } else 237 #endif /*FAST_IPSEC*/ 238 /* Check the minimum TTL for socket. */ 239 if (last && ip->ip_ttl < last->inp_ip_minttl) { 240 m_freem(opts); 241 ipstat.ips_delivered--; 242 } else if (last) { 243 if (last->inp_flags & INP_CONTROLOPTS || 244 last->inp_socket->so_options & SO_TIMESTAMP) 245 ip_savecontrol(last, &opts, ip, m); 246 lwkt_gettoken(&last->inp_socket->so_rcv.ssb_token); 247 if (ssb_appendaddr(&last->inp_socket->so_rcv, 248 (struct sockaddr *)&ripsrc, m, opts) == 0) { 249 m_freem(m); 250 if (opts) 251 m_freem(opts); 252 } else { 253 sorwakeup(last->inp_socket); 254 } 255 lwkt_reltoken(&last->inp_socket->so_rcv.ssb_token); 256 } else { 257 m_freem(m); 258 ipstat.ips_noproto++; 259 ipstat.ips_delivered--; 260 } 261 lwkt_reltoken(&raw_token); 262 return(IPPROTO_DONE); 263 } 264 265 /* 266 * Generate IP header and pass packet to ip_output. 267 * Tack on options user may have setup with control call. 268 */ 269 int 270 rip_output(struct mbuf *m, struct socket *so, ...) 271 { 272 struct ip *ip; 273 struct inpcb *inp = so->so_pcb; 274 __va_list ap; 275 int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST; 276 u_long dst; 277 278 __va_start(ap, so); 279 dst = __va_arg(ap, u_long); 280 __va_end(ap); 281 282 /* 283 * If the user handed us a complete IP packet, use it. 284 * Otherwise, allocate an mbuf for a header and fill it in. 285 */ 286 if ((inp->inp_flags & INP_HDRINCL) == 0) { 287 if (m->m_pkthdr.len + sizeof(struct ip) > IP_MAXPACKET) { 288 m_freem(m); 289 return(EMSGSIZE); 290 } 291 M_PREPEND(m, sizeof(struct ip), MB_WAIT); 292 if (m == NULL) 293 return(ENOBUFS); 294 ip = mtod(m, struct ip *); 295 ip->ip_tos = inp->inp_ip_tos; 296 ip->ip_off = 0; 297 ip->ip_p = inp->inp_ip_p; 298 ip->ip_len = m->m_pkthdr.len; 299 ip->ip_src = inp->inp_laddr; 300 ip->ip_dst.s_addr = dst; 301 ip->ip_ttl = inp->inp_ip_ttl; 302 } else { 303 int hlen; 304 305 if (m->m_pkthdr.len > IP_MAXPACKET) { 306 m_freem(m); 307 return(EMSGSIZE); 308 } 309 if (m->m_len < sizeof(struct ip)) { 310 m = m_pullup(m, sizeof(struct ip)); 311 if (m == NULL) 312 return ENOBUFS; 313 } 314 ip = mtod(m, struct ip *); 315 hlen = IP_VHL_HL(ip->ip_vhl) << 2; 316 317 /* Don't allow header length less than the minimum. */ 318 if (hlen < sizeof(struct ip)) { 319 m_freem(m); 320 return EINVAL; 321 } 322 323 /* 324 * Don't allow both user specified and setsockopt options. 325 * Don't allow packet length sizes that will crash. 326 */ 327 if ((hlen != sizeof(struct ip) && inp->inp_options) || 328 ip->ip_len > m->m_pkthdr.len || ip->ip_len < hlen) { 329 m_freem(m); 330 return EINVAL; 331 } 332 if (ip->ip_id == 0) 333 ip->ip_id = ip_newid(); 334 335 /* Prevent ip_output from overwriting header fields */ 336 flags |= IP_RAWOUTPUT; 337 ipstat.ips_rawout++; 338 } 339 340 return ip_output(m, inp->inp_options, &inp->inp_route, flags, 341 inp->inp_moptions, inp); 342 } 343 344 /* 345 * Raw IP socket option processing. 346 */ 347 void 348 rip_ctloutput(netmsg_t msg) 349 { 350 struct socket *so = msg->base.nm_so; 351 struct sockopt *sopt = msg->ctloutput.nm_sopt; 352 struct inpcb *inp = so->so_pcb; 353 int error, optval; 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 switch (cmd) { 495 case PRC_IFDOWN: 496 TAILQ_FOREACH(iac, &in_ifaddrheads[mycpuid], ia_link) { 497 ia = iac->ia; 498 499 if (ia->ia_ifa.ifa_addr == sa && 500 (ia->ia_flags & IFA_ROUTE)) { 501 /* 502 * in_ifscrub kills the interface route. 503 */ 504 in_ifscrub(ia->ia_ifp, ia); 505 /* 506 * in_ifadown gets rid of all the rest of 507 * the routes. This is not quite the right 508 * thing to do, but at least if we are running 509 * a routing process they will come back. 510 */ 511 in_ifadown(&ia->ia_ifa, 0); 512 break; 513 } 514 } 515 break; 516 517 case PRC_IFUP: 518 ia = NULL; 519 TAILQ_FOREACH(iac, &in_ifaddrheads[mycpuid], ia_link) { 520 if (iac->ia->ia_ifa.ifa_addr == sa) { 521 ia = iac->ia; 522 break; 523 } 524 } 525 if (ia == NULL || (ia->ia_flags & IFA_ROUTE)) 526 goto done; 527 flags = RTF_UP; 528 ifp = ia->ia_ifa.ifa_ifp; 529 530 #ifdef CARP 531 /* 532 * Don't add prefix routes for CARP interfaces. 533 * Prefix routes creation is handled by CARP 534 * interfaces themselves. 535 */ 536 if (ifp->if_type == IFT_CARP) 537 goto done; 538 #endif 539 540 if ((ifp->if_flags & IFF_LOOPBACK) || 541 (ifp->if_flags & IFF_POINTOPOINT)) 542 flags |= RTF_HOST; 543 544 err = rtinit(&ia->ia_ifa, RTM_ADD, flags); 545 if (err == 0) 546 ia->ia_flags |= IFA_ROUTE; 547 break; 548 } 549 done: 550 lwkt_replymsg(&msg->lmsg, 0); 551 } 552 553 u_long rip_sendspace = RIPSNDQ; 554 u_long rip_recvspace = RIPRCVQ; 555 556 SYSCTL_INT(_net_inet_raw, OID_AUTO, maxdgram, CTLFLAG_RW, 557 &rip_sendspace, 0, "Maximum outgoing raw IP datagram size"); 558 SYSCTL_INT(_net_inet_raw, OID_AUTO, recvspace, CTLFLAG_RW, 559 &rip_recvspace, 0, "Maximum incoming raw IP datagram size"); 560 561 static void 562 rip_attach(netmsg_t msg) 563 { 564 struct socket *so = msg->base.nm_so; 565 int proto = msg->attach.nm_proto; 566 struct pru_attach_info *ai = msg->attach.nm_ai; 567 struct inpcb *inp; 568 int error; 569 570 inp = so->so_pcb; 571 if (inp) 572 panic("rip_attach"); 573 error = priv_check_cred(ai->p_ucred, PRIV_NETINET_RAW, NULL_CRED_OKAY); 574 if (error) 575 goto done; 576 577 error = soreserve(so, rip_sendspace, rip_recvspace, ai->sb_rlimit); 578 if (error) 579 goto done; 580 581 lwkt_gettoken(&raw_token); 582 error = in_pcballoc(so, &ripcbinfo); 583 if (error == 0) { 584 inp = (struct inpcb *)so->so_pcb; 585 inp->inp_vflag |= INP_IPV4; 586 inp->inp_ip_p = proto; 587 inp->inp_ip_ttl = ip_defttl; 588 } 589 lwkt_reltoken(&raw_token); 590 error = 0; 591 done: 592 lwkt_replymsg(&msg->lmsg, error); 593 } 594 595 static void 596 rip_detach(netmsg_t msg) 597 { 598 struct socket *so = msg->base.nm_so; 599 struct inpcb *inp; 600 601 inp = so->so_pcb; 602 if (inp == NULL) 603 panic("rip_detach"); 604 if (so == ip_mrouter && ip_mrouter_done) 605 ip_mrouter_done(); 606 if (ip_rsvp_force_done) 607 ip_rsvp_force_done(so); 608 if (so == ip_rsvpd) 609 ip_rsvp_done(); 610 in_pcbdetach(inp); 611 lwkt_replymsg(&msg->lmsg, 0); 612 } 613 614 /* 615 * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort() 616 * will sofree() it when we return. 617 */ 618 static void 619 rip_abort(netmsg_t msg) 620 { 621 struct socket *so = msg->base.nm_so; 622 int error; 623 624 soisdisconnected(so); 625 if (so->so_state & SS_NOFDREF) { /* XXX not sure why this test */ 626 rip_detach(msg); 627 /* msg invalid now */ 628 return; 629 } 630 error = 0; 631 lwkt_replymsg(&msg->lmsg, error); 632 } 633 634 static void 635 rip_disconnect(netmsg_t msg) 636 { 637 struct socket *so = msg->base.nm_so; 638 int error; 639 640 if (so->so_state & SS_ISCONNECTED) { 641 soreference(so); 642 rip_abort(msg); 643 /* msg invalid now */ 644 sofree(so); 645 return; 646 } 647 error = ENOTCONN; 648 lwkt_replymsg(&msg->lmsg, error); 649 } 650 651 static void 652 rip_bind(netmsg_t msg) 653 { 654 struct socket *so = msg->base.nm_so; 655 struct sockaddr *nam = msg->bind.nm_nam; 656 struct inpcb *inp = so->so_pcb; 657 struct sockaddr_in *addr = (struct sockaddr_in *)nam; 658 int error; 659 660 if (nam->sa_len == sizeof(*addr)) { 661 if (TAILQ_EMPTY(&ifnet) || 662 ((addr->sin_family != AF_INET) && 663 (addr->sin_family != AF_IMPLINK)) || 664 (addr->sin_addr.s_addr != INADDR_ANY && 665 ifa_ifwithaddr((struct sockaddr *)addr) == 0)) { 666 error = EADDRNOTAVAIL; 667 } else { 668 inp->inp_laddr = addr->sin_addr; 669 error = 0; 670 } 671 } else { 672 error = EINVAL; 673 } 674 lwkt_replymsg(&msg->lmsg, error); 675 } 676 677 static void 678 rip_connect(netmsg_t msg) 679 { 680 struct socket *so = msg->base.nm_so; 681 struct sockaddr *nam = msg->connect.nm_nam; 682 struct inpcb *inp = so->so_pcb; 683 struct sockaddr_in *addr = (struct sockaddr_in *)nam; 684 int error; 685 686 if (nam->sa_len != sizeof(*addr)) { 687 error = EINVAL; 688 } else if (TAILQ_EMPTY(&ifnet)) { 689 error = EADDRNOTAVAIL; 690 } else { 691 if ((addr->sin_family != AF_INET) && 692 (addr->sin_family != AF_IMPLINK)) { 693 error = EAFNOSUPPORT; 694 } else { 695 inp->inp_faddr = addr->sin_addr; 696 soisconnected(so); 697 error = 0; 698 } 699 } 700 lwkt_replymsg(&msg->lmsg, error); 701 } 702 703 static void 704 rip_shutdown(netmsg_t msg) 705 { 706 socantsendmore(msg->base.nm_so); 707 lwkt_replymsg(&msg->lmsg, 0); 708 } 709 710 static void 711 rip_send(netmsg_t msg) 712 { 713 struct socket *so = msg->base.nm_so; 714 struct mbuf *m = msg->send.nm_m; 715 /*struct mbuf *control = msg->send.nm_control;*/ 716 struct sockaddr *nam = msg->send.nm_addr; 717 /*int flags = msg->send.nm_flags;*/ 718 struct inpcb *inp = so->so_pcb; 719 u_long dst; 720 int error; 721 722 if (so->so_state & SS_ISCONNECTED) { 723 if (nam) { 724 m_freem(m); 725 error = EISCONN; 726 } else { 727 dst = inp->inp_faddr.s_addr; 728 error = rip_output(m, so, dst); 729 } 730 } else { 731 if (nam == NULL) { 732 m_freem(m); 733 error = ENOTCONN; 734 } else { 735 dst = ((struct sockaddr_in *)nam)->sin_addr.s_addr; 736 error = rip_output(m, so, dst); 737 } 738 } 739 lwkt_replymsg(&msg->lmsg, error); 740 } 741 742 SYSCTL_PROC(_net_inet_raw, OID_AUTO/*XXX*/, pcblist, CTLFLAG_RD, &ripcbinfo, 0, 743 in_pcblist_global, "S,xinpcb", "List of active raw IP sockets"); 744 745 struct pr_usrreqs rip_usrreqs = { 746 .pru_abort = rip_abort, 747 .pru_accept = pr_generic_notsupp, 748 .pru_attach = rip_attach, 749 .pru_bind = rip_bind, 750 .pru_connect = rip_connect, 751 .pru_connect2 = pr_generic_notsupp, 752 .pru_control = in_control_dispatch, 753 .pru_detach = rip_detach, 754 .pru_disconnect = rip_disconnect, 755 .pru_listen = pr_generic_notsupp, 756 .pru_peeraddr = in_setpeeraddr_dispatch, 757 .pru_rcvd = pr_generic_notsupp, 758 .pru_rcvoob = pr_generic_notsupp, 759 .pru_send = rip_send, 760 .pru_sense = pru_sense_null, 761 .pru_shutdown = rip_shutdown, 762 .pru_sockaddr = in_setsockaddr_dispatch, 763 .pru_sosend = sosend, 764 .pru_soreceive = soreceive 765 }; 766