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