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 * $DragonFly: src/sys/netinet/raw_ip.c,v 1.33 2008/10/28 03:07:28 sephe Exp $ 36 */ 37 38 #include "opt_inet6.h" 39 #include "opt_ipsec.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 #include <net/route.h> 62 63 #define _IP_VHL 64 #include <netinet/in.h> 65 #include <netinet/in_systm.h> 66 #include <netinet/ip.h> 67 #include <netinet/in_pcb.h> 68 #include <netinet/in_var.h> 69 #include <netinet/ip_var.h> 70 71 #include <net/ip_mroute/ip_mroute.h> 72 #include <net/ipfw/ip_fw.h> 73 #include <net/dummynet/ip_dummynet.h> 74 75 #ifdef FAST_IPSEC 76 #include <netproto/ipsec/ipsec.h> 77 #endif /*FAST_IPSEC*/ 78 79 #ifdef IPSEC 80 #include <netinet6/ipsec.h> 81 #endif /*IPSEC*/ 82 83 struct inpcbinfo ripcbinfo; 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 static struct lwkt_token raw_token = LWKT_TOKEN_INITIALIZER(raw_token); 90 91 92 /* 93 * hooks for multicast routing. They all default to NULL, 94 * so leave them not initialized and rely on BSS being set to 0. 95 */ 96 97 /* The socket used to communicate with the multicast routing daemon. */ 98 struct socket *ip_mrouter; 99 100 /* The various mrouter and rsvp functions */ 101 int (*ip_mrouter_set)(struct socket *, struct sockopt *); 102 int (*ip_mrouter_get)(struct socket *, struct sockopt *); 103 int (*ip_mrouter_done)(void); 104 int (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *, 105 struct ip_moptions *); 106 int (*mrt_ioctl)(int, caddr_t); 107 int (*legal_vif_num)(int); 108 u_long (*ip_mcast_src)(int); 109 110 int (*rsvp_input_p)(struct mbuf **, int *, int); 111 int (*ip_rsvp_vif)(struct socket *, struct sockopt *); 112 void (*ip_rsvp_force_done)(struct socket *); 113 114 /* 115 * Nominal space allocated to a raw ip socket. 116 */ 117 #define RIPSNDQ 8192 118 #define RIPRCVQ 8192 119 120 /* 121 * Raw interface to IP protocol. 122 */ 123 124 /* 125 * Initialize raw connection block queue. 126 */ 127 void 128 rip_init(void) 129 { 130 in_pcbinfo_init(&ripcbinfo); 131 /* 132 * XXX We don't use the hash list for raw IP, but it's easier 133 * to allocate a one entry hash list than it is to check all 134 * over the place for hashbase == NULL. 135 */ 136 ripcbinfo.hashbase = hashinit(1, M_PCB, &ripcbinfo.hashmask); 137 ripcbinfo.porthashbase = hashinit(1, M_PCB, &ripcbinfo.porthashmask); 138 ripcbinfo.wildcardhashbase = hashinit(1, M_PCB, 139 &ripcbinfo.wildcardhashmask); 140 ripcbinfo.ipi_size = sizeof(struct inpcb); 141 } 142 143 /* 144 * Setup generic address and protocol structures 145 * for raw_input routine, then pass them along with 146 * mbuf chain. 147 */ 148 int 149 rip_input(struct mbuf **mp, int *offp, int proto) 150 { 151 struct sockaddr_in ripsrc = { sizeof ripsrc, AF_INET }; 152 struct mbuf *m = *mp; 153 struct ip *ip = mtod(m, struct ip *); 154 struct inpcb *inp; 155 struct inpcb *last = NULL; 156 struct mbuf *opts = NULL; 157 int off; 158 159 off = *offp; 160 *mp = NULL; 161 162 ripsrc.sin_addr = ip->ip_src; 163 lwkt_gettoken(&raw_token); 164 LIST_FOREACH(inp, &ripcbinfo.pcblisthead, inp_list) { 165 if (inp->inp_flags & INP_PLACEMARKER) 166 continue; 167 #ifdef INET6 168 if ((inp->inp_vflag & INP_IPV4) == 0) 169 continue; 170 #endif 171 if (inp->inp_ip_p && inp->inp_ip_p != proto) 172 continue; 173 if (inp->inp_laddr.s_addr != INADDR_ANY && 174 inp->inp_laddr.s_addr != ip->ip_dst.s_addr) 175 continue; 176 if (inp->inp_faddr.s_addr != INADDR_ANY && 177 inp->inp_faddr.s_addr != ip->ip_src.s_addr) 178 continue; 179 if (last) { 180 struct mbuf *n = m_copypacket(m, MB_DONTWAIT); 181 182 #ifdef IPSEC 183 /* check AH/ESP integrity. */ 184 if (n && ipsec4_in_reject_so(n, last->inp_socket)) { 185 m_freem(n); 186 ipsecstat.in_polvio++; 187 /* do not inject data to pcb */ 188 } else 189 #endif /*IPSEC*/ 190 #ifdef FAST_IPSEC 191 /* check AH/ESP integrity. */ 192 if (ipsec4_in_reject(n, last)) { 193 m_freem(n); 194 /* do not inject data to pcb */ 195 } else 196 #endif /*FAST_IPSEC*/ 197 if (n) { 198 lwkt_gettoken(&last->inp_socket->so_rcv.ssb_token); 199 if (last->inp_flags & INP_CONTROLOPTS || 200 last->inp_socket->so_options & SO_TIMESTAMP) 201 ip_savecontrol(last, &opts, ip, n); 202 if (ssb_appendaddr(&last->inp_socket->so_rcv, 203 (struct sockaddr *)&ripsrc, n, 204 opts) == 0) { 205 /* should notify about lost packet */ 206 m_freem(n); 207 if (opts) 208 m_freem(opts); 209 } else { 210 sorwakeup(last->inp_socket); 211 } 212 lwkt_reltoken(&last->inp_socket->so_rcv.ssb_token); 213 opts = 0; 214 } 215 } 216 last = inp; 217 } 218 #ifdef IPSEC 219 /* check AH/ESP integrity. */ 220 if (last && ipsec4_in_reject_so(m, last->inp_socket)) { 221 m_freem(m); 222 ipsecstat.in_polvio++; 223 ipstat.ips_delivered--; 224 /* do not inject data to pcb */ 225 } else 226 #endif /*IPSEC*/ 227 #ifdef FAST_IPSEC 228 /* check AH/ESP integrity. */ 229 if (last && ipsec4_in_reject(m, last)) { 230 m_freem(m); 231 ipstat.ips_delivered--; 232 /* do not inject data to pcb */ 233 } else 234 #endif /*FAST_IPSEC*/ 235 /* Check the minimum TTL for socket. */ 236 if (last && ip->ip_ttl < last->inp_ip_minttl) { 237 m_freem(opts); 238 ipstat.ips_delivered--; 239 } else if (last) { 240 if (last->inp_flags & INP_CONTROLOPTS || 241 last->inp_socket->so_options & SO_TIMESTAMP) 242 ip_savecontrol(last, &opts, ip, m); 243 lwkt_gettoken(&last->inp_socket->so_rcv.ssb_token); 244 if (ssb_appendaddr(&last->inp_socket->so_rcv, 245 (struct sockaddr *)&ripsrc, m, opts) == 0) { 246 m_freem(m); 247 if (opts) 248 m_freem(opts); 249 } else { 250 sorwakeup(last->inp_socket); 251 } 252 lwkt_reltoken(&last->inp_socket->so_rcv.ssb_token); 253 } else { 254 m_freem(m); 255 ipstat.ips_noproto++; 256 ipstat.ips_delivered--; 257 } 258 lwkt_reltoken(&raw_token); 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 __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 if (sopt->sopt_level != IPPROTO_IP) { 353 error = EINVAL; 354 goto done; 355 } 356 357 error = 0; 358 359 switch (sopt->sopt_dir) { 360 case SOPT_GET: 361 switch (sopt->sopt_name) { 362 case IP_HDRINCL: 363 optval = inp->inp_flags & INP_HDRINCL; 364 soopt_from_kbuf(sopt, &optval, sizeof optval); 365 break; 366 367 case IP_FW_ADD: /* ADD actually returns the body... */ 368 case IP_FW_GET: 369 if (IPFW_LOADED) 370 error = ip_fw_sockopt(sopt); 371 else 372 error = ENOPROTOOPT; 373 break; 374 375 case IP_DUMMYNET_GET: 376 error = ip_dn_sockopt(sopt); 377 break ; 378 379 case MRT_INIT: 380 case MRT_DONE: 381 case MRT_ADD_VIF: 382 case MRT_DEL_VIF: 383 case MRT_ADD_MFC: 384 case MRT_DEL_MFC: 385 case MRT_VERSION: 386 case MRT_ASSERT: 387 case MRT_API_SUPPORT: 388 case MRT_API_CONFIG: 389 case MRT_ADD_BW_UPCALL: 390 case MRT_DEL_BW_UPCALL: 391 error = ip_mrouter_get ? ip_mrouter_get(so, sopt) : 392 EOPNOTSUPP; 393 break; 394 395 default: 396 ip_ctloutput(msg); 397 /* msg invalid now */ 398 return; 399 } 400 break; 401 402 case SOPT_SET: 403 switch (sopt->sopt_name) { 404 case IP_HDRINCL: 405 error = soopt_to_kbuf(sopt, &optval, sizeof optval, 406 sizeof optval); 407 if (error) 408 break; 409 if (optval) 410 inp->inp_flags |= INP_HDRINCL; 411 else 412 inp->inp_flags &= ~INP_HDRINCL; 413 break; 414 415 case IP_FW_ADD: 416 case IP_FW_DEL: 417 case IP_FW_FLUSH: 418 case IP_FW_ZERO: 419 case IP_FW_RESETLOG: 420 if (IPFW_LOADED) 421 error = ip_fw_ctl_ptr(sopt); 422 else 423 error = ENOPROTOOPT; 424 break; 425 426 case IP_DUMMYNET_CONFIGURE: 427 case IP_DUMMYNET_DEL: 428 case IP_DUMMYNET_FLUSH: 429 error = ip_dn_sockopt(sopt); 430 break ; 431 432 case IP_RSVP_ON: 433 error = ip_rsvp_init(so); 434 break; 435 436 case IP_RSVP_OFF: 437 error = ip_rsvp_done(); 438 break; 439 440 case IP_RSVP_VIF_ON: 441 case IP_RSVP_VIF_OFF: 442 error = ip_rsvp_vif ? 443 ip_rsvp_vif(so, sopt) : EINVAL; 444 break; 445 446 case MRT_INIT: 447 case MRT_DONE: 448 case MRT_ADD_VIF: 449 case MRT_DEL_VIF: 450 case MRT_ADD_MFC: 451 case MRT_DEL_MFC: 452 case MRT_VERSION: 453 case MRT_ASSERT: 454 case MRT_API_SUPPORT: 455 case MRT_API_CONFIG: 456 case MRT_ADD_BW_UPCALL: 457 case MRT_DEL_BW_UPCALL: 458 error = ip_mrouter_set ? ip_mrouter_set(so, sopt) : 459 EOPNOTSUPP; 460 break; 461 462 default: 463 ip_ctloutput(msg); 464 /* msg invalid now */ 465 return; 466 } 467 break; 468 } 469 done: 470 lwkt_replymsg(&msg->lmsg, error); 471 } 472 473 /* 474 * This function exists solely to receive the PRC_IFDOWN messages which 475 * are sent by if_down(). It looks for an ifaddr whose ifa_addr is sa, 476 * and calls in_ifadown() to remove all routes corresponding to that address. 477 * It also receives the PRC_IFUP messages from if_up() and reinstalls the 478 * interface routes. 479 */ 480 void 481 rip_ctlinput(netmsg_t msg) 482 { 483 int cmd = msg->ctlinput.nm_cmd; 484 struct sockaddr *sa = msg->ctlinput.nm_arg; 485 struct in_ifaddr *ia; 486 struct in_ifaddr_container *iac; 487 struct ifnet *ifp; 488 int err; 489 int flags; 490 491 switch (cmd) { 492 case PRC_IFDOWN: 493 TAILQ_FOREACH(iac, &in_ifaddrheads[mycpuid], ia_link) { 494 ia = iac->ia; 495 496 if (ia->ia_ifa.ifa_addr == sa && 497 (ia->ia_flags & IFA_ROUTE)) { 498 /* 499 * in_ifscrub kills the interface route. 500 */ 501 in_ifscrub(ia->ia_ifp, ia); 502 /* 503 * in_ifadown gets rid of all the rest of 504 * the routes. This is not quite the right 505 * thing to do, but at least if we are running 506 * a routing process they will come back. 507 */ 508 in_ifadown(&ia->ia_ifa, 0); 509 break; 510 } 511 } 512 break; 513 514 case PRC_IFUP: 515 ia = NULL; 516 TAILQ_FOREACH(iac, &in_ifaddrheads[mycpuid], ia_link) { 517 if (iac->ia->ia_ifa.ifa_addr == sa) { 518 ia = iac->ia; 519 break; 520 } 521 } 522 if (ia == NULL || (ia->ia_flags & IFA_ROUTE)) 523 goto done; 524 flags = RTF_UP; 525 ifp = ia->ia_ifa.ifa_ifp; 526 527 if ((ifp->if_flags & IFF_LOOPBACK) || 528 (ifp->if_flags & IFF_POINTOPOINT)) 529 flags |= RTF_HOST; 530 531 err = rtinit(&ia->ia_ifa, RTM_ADD, flags); 532 if (err == 0) 533 ia->ia_flags |= IFA_ROUTE; 534 break; 535 } 536 done: 537 lwkt_replymsg(&msg->lmsg, 0); 538 } 539 540 u_long rip_sendspace = RIPSNDQ; 541 u_long rip_recvspace = RIPRCVQ; 542 543 SYSCTL_INT(_net_inet_raw, OID_AUTO, maxdgram, CTLFLAG_RW, 544 &rip_sendspace, 0, "Maximum outgoing raw IP datagram size"); 545 SYSCTL_INT(_net_inet_raw, OID_AUTO, recvspace, CTLFLAG_RW, 546 &rip_recvspace, 0, "Maximum incoming raw IP datagram size"); 547 548 static void 549 rip_attach(netmsg_t msg) 550 { 551 struct socket *so = msg->base.nm_so; 552 int proto = msg->attach.nm_proto; 553 struct pru_attach_info *ai = msg->attach.nm_ai; 554 struct inpcb *inp; 555 int error; 556 557 inp = so->so_pcb; 558 if (inp) 559 panic("rip_attach"); 560 error = priv_check_cred(ai->p_ucred, PRIV_NETINET_RAW, NULL_CRED_OKAY); 561 if (error) 562 goto done; 563 564 error = soreserve(so, rip_sendspace, rip_recvspace, ai->sb_rlimit); 565 if (error) 566 goto done; 567 568 lwkt_gettoken(&raw_token); 569 error = in_pcballoc(so, &ripcbinfo); 570 if (error == 0) { 571 inp = (struct inpcb *)so->so_pcb; 572 inp->inp_vflag |= INP_IPV4; 573 inp->inp_ip_p = proto; 574 inp->inp_ip_ttl = ip_defttl; 575 } 576 lwkt_reltoken(&raw_token); 577 error = 0; 578 done: 579 lwkt_replymsg(&msg->lmsg, error); 580 } 581 582 static void 583 rip_detach(netmsg_t msg) 584 { 585 struct socket *so = msg->base.nm_so; 586 struct inpcb *inp; 587 588 inp = so->so_pcb; 589 if (inp == 0) 590 panic("rip_detach"); 591 if (so == ip_mrouter && ip_mrouter_done) 592 ip_mrouter_done(); 593 if (ip_rsvp_force_done) 594 ip_rsvp_force_done(so); 595 if (so == ip_rsvpd) 596 ip_rsvp_done(); 597 in_pcbdetach(inp); 598 lwkt_replymsg(&msg->lmsg, 0); 599 } 600 601 /* 602 * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort() 603 * will sofree() it when we return. 604 */ 605 static void 606 rip_abort(netmsg_t msg) 607 { 608 struct socket *so = msg->base.nm_so; 609 int error; 610 611 soisdisconnected(so); 612 if (so->so_state & SS_NOFDREF) { /* XXX not sure why this test */ 613 rip_detach(msg); 614 /* msg invalid now */ 615 return; 616 } 617 error = 0; 618 lwkt_replymsg(&msg->lmsg, error); 619 } 620 621 static void 622 rip_disconnect(netmsg_t msg) 623 { 624 struct socket *so = msg->base.nm_so; 625 int error; 626 627 if (so->so_state & SS_ISCONNECTED) { 628 soreference(so); 629 rip_abort(msg); 630 /* msg invalid now */ 631 sofree(so); 632 return; 633 } 634 error = ENOTCONN; 635 lwkt_replymsg(&msg->lmsg, error); 636 } 637 638 static void 639 rip_bind(netmsg_t msg) 640 { 641 struct socket *so = msg->base.nm_so; 642 struct sockaddr *nam = msg->bind.nm_nam; 643 struct inpcb *inp = so->so_pcb; 644 struct sockaddr_in *addr = (struct sockaddr_in *)nam; 645 int error; 646 647 if (nam->sa_len == sizeof(*addr)) { 648 if (TAILQ_EMPTY(&ifnet) || 649 ((addr->sin_family != AF_INET) && 650 (addr->sin_family != AF_IMPLINK)) || 651 (addr->sin_addr.s_addr != INADDR_ANY && 652 ifa_ifwithaddr((struct sockaddr *)addr) == 0)) { 653 error = EADDRNOTAVAIL; 654 } else { 655 inp->inp_laddr = addr->sin_addr; 656 error = 0; 657 } 658 } else { 659 error = EINVAL; 660 } 661 lwkt_replymsg(&msg->lmsg, error); 662 } 663 664 static void 665 rip_connect(netmsg_t msg) 666 { 667 struct socket *so = msg->base.nm_so; 668 struct sockaddr *nam = msg->connect.nm_nam; 669 struct inpcb *inp = so->so_pcb; 670 struct sockaddr_in *addr = (struct sockaddr_in *)nam; 671 int error; 672 673 if (nam->sa_len != sizeof(*addr)) { 674 error = EINVAL; 675 } else if (TAILQ_EMPTY(&ifnet)) { 676 error = EADDRNOTAVAIL; 677 } else { 678 if ((addr->sin_family != AF_INET) && 679 (addr->sin_family != AF_IMPLINK)) { 680 error = EAFNOSUPPORT; 681 } else { 682 inp->inp_faddr = addr->sin_addr; 683 soisconnected(so); 684 error = 0; 685 } 686 } 687 lwkt_replymsg(&msg->lmsg, error); 688 } 689 690 static void 691 rip_shutdown(netmsg_t msg) 692 { 693 socantsendmore(msg->base.nm_so); 694 lwkt_replymsg(&msg->lmsg, 0); 695 } 696 697 static void 698 rip_send(netmsg_t msg) 699 { 700 struct socket *so = msg->base.nm_so; 701 struct mbuf *m = msg->send.nm_m; 702 /*struct mbuf *control = msg->send.nm_control;*/ 703 struct sockaddr *nam = msg->send.nm_addr; 704 /*int flags = msg->send.nm_flags;*/ 705 struct inpcb *inp = so->so_pcb; 706 u_long dst; 707 int error; 708 709 if (so->so_state & SS_ISCONNECTED) { 710 if (nam) { 711 m_freem(m); 712 error = EISCONN; 713 } else { 714 dst = inp->inp_faddr.s_addr; 715 error = rip_output(m, so, dst); 716 } 717 } else { 718 if (nam == NULL) { 719 m_freem(m); 720 error = ENOTCONN; 721 } else { 722 dst = ((struct sockaddr_in *)nam)->sin_addr.s_addr; 723 error = rip_output(m, so, dst); 724 } 725 } 726 lwkt_replymsg(&msg->lmsg, error); 727 } 728 729 SYSCTL_PROC(_net_inet_raw, OID_AUTO/*XXX*/, pcblist, CTLFLAG_RD, &ripcbinfo, 0, 730 in_pcblist_global, "S,xinpcb", "List of active raw IP sockets"); 731 732 struct pr_usrreqs rip_usrreqs = { 733 .pru_abort = rip_abort, 734 .pru_accept = pr_generic_notsupp, 735 .pru_attach = rip_attach, 736 .pru_bind = rip_bind, 737 .pru_connect = rip_connect, 738 .pru_connect2 = pr_generic_notsupp, 739 .pru_control = in_control_dispatch, 740 .pru_detach = rip_detach, 741 .pru_disconnect = rip_disconnect, 742 .pru_listen = pr_generic_notsupp, 743 .pru_peeraddr = in_setpeeraddr_dispatch, 744 .pru_rcvd = pr_generic_notsupp, 745 .pru_rcvoob = pr_generic_notsupp, 746 .pru_send = rip_send, 747 .pru_sense = pru_sense_null, 748 .pru_shutdown = rip_shutdown, 749 .pru_sockaddr = in_setsockaddr_dispatch, 750 .pru_sosend = sosend, 751 .pru_soreceive = soreceive 752 }; 753