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