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