1 /* $NetBSD: raw_ip.c,v 1.186 2024/07/05 04:31:54 rin Exp $ */ 2 3 /* 4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright (c) 1982, 1986, 1988, 1993 34 * The Regents of the University of California. All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. Neither the name of the University nor the names of its contributors 45 * may be used to endorse or promote products derived from this software 46 * without specific prior written permission. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 * 60 * @(#)raw_ip.c 8.7 (Berkeley) 5/15/95 61 */ 62 63 /* 64 * Raw interface to IP protocol. 65 */ 66 67 #include <sys/cdefs.h> 68 __KERNEL_RCSID(0, "$NetBSD: raw_ip.c,v 1.186 2024/07/05 04:31:54 rin Exp $"); 69 70 #ifdef _KERNEL_OPT 71 #include "opt_inet.h" 72 #include "opt_ipsec.h" 73 #include "opt_mrouting.h" 74 #include "opt_net_mpsafe.h" 75 #endif 76 77 #include <sys/param.h> 78 #include <sys/sysctl.h> 79 #include <sys/mbuf.h> 80 #include <sys/socket.h> 81 #include <sys/protosw.h> 82 #include <sys/socketvar.h> 83 #include <sys/errno.h> 84 #include <sys/systm.h> 85 #include <sys/proc.h> 86 #include <sys/kauth.h> 87 88 #include <net/if.h> 89 90 #include <netinet/in.h> 91 #include <netinet/in_systm.h> 92 #include <netinet/ip.h> 93 #include <netinet/ip_var.h> 94 #include <netinet/ip_private.h> 95 #include <netinet/ip_mroute.h> 96 #include <netinet/ip_icmp.h> 97 #include <netinet/in_pcb.h> 98 #include <netinet/in_proto.h> 99 #include <netinet/in_var.h> 100 101 #ifdef IPSEC 102 #include <netipsec/ipsec.h> 103 #endif 104 105 struct inpcbtable rawcbtable; 106 107 int rip_pcbnotify(struct inpcbtable *, struct in_addr, 108 struct in_addr, int, int, void (*)(struct inpcb *, int)); 109 static int rip_connect_pcb(struct inpcb *, struct sockaddr_in *); 110 static void rip_disconnect1(struct inpcb *); 111 112 static void sysctl_net_inet_raw_setup(struct sysctllog **); 113 114 /* 115 * Nominal space allocated to a raw ip socket. 116 */ 117 #define RIPSNDQ 8192 118 #define RIPRCVQ 8192 119 120 static u_long rip_sendspace = RIPSNDQ; 121 static u_long rip_recvspace = RIPRCVQ; 122 123 /* 124 * Raw interface to IP protocol. 125 */ 126 127 /* 128 * Initialize raw connection block q. 129 */ 130 void 131 rip_init(void) 132 { 133 134 sysctl_net_inet_raw_setup(NULL); 135 inpcb_init(&rawcbtable, 1, 1); 136 } 137 138 static void 139 rip_sbappendaddr(struct inpcb *last, struct ip *ip, const struct sockaddr *sa, 140 int hlen, struct mbuf *n) 141 { 142 struct mbuf *opts = NULL; 143 144 if (last->inp_flags & INP_NOHEADER) 145 m_adj(n, hlen); 146 if (last->inp_flags & INP_CONTROLOPTS || 147 SOOPT_TIMESTAMP(last->inp_socket->so_options)) 148 ip_savecontrol(last, &opts, ip, n); 149 if (sbappendaddr(&last->inp_socket->so_rcv, sa, n, opts) == 0) { 150 soroverflow(last->inp_socket); 151 m_freem(n); 152 m_freem(opts); 153 } else { 154 sorwakeup(last->inp_socket); 155 } 156 } 157 158 /* 159 * Setup generic address and protocol structures 160 * for raw_input routine, then pass them along with 161 * mbuf chain. 162 */ 163 void 164 rip_input(struct mbuf *m, int off, int proto) 165 { 166 struct ip *ip = mtod(m, struct ip *); 167 struct inpcb *inp; 168 struct inpcb *last = NULL; 169 struct mbuf *n; 170 struct sockaddr_in ripsrc; 171 int hlen; 172 173 sockaddr_in_init(&ripsrc, &ip->ip_src, 0); 174 175 /* 176 * XXX Compatibility: programs using raw IP expect ip_len 177 * XXX to have the header length subtracted, and in host order. 178 * XXX ip_off is also expected to be host order. 179 */ 180 hlen = ip->ip_hl << 2; 181 ip->ip_len = ntohs(ip->ip_len) - hlen; 182 NTOHS(ip->ip_off); 183 184 TAILQ_FOREACH(inp, &rawcbtable.inpt_queue, inp_queue) { 185 if (inp->inp_af != AF_INET) 186 continue; 187 if (in4p_ip(inp).ip_p && in4p_ip(inp).ip_p != proto) 188 continue; 189 if (!in_nullhost(in4p_laddr(inp)) && 190 !in_hosteq(in4p_laddr(inp), ip->ip_dst)) 191 continue; 192 if (!in_nullhost(in4p_faddr(inp)) && 193 !in_hosteq(in4p_faddr(inp), ip->ip_src)) 194 continue; 195 196 if (last == NULL) { 197 ; 198 } 199 #if defined(IPSEC) 200 else if (ipsec_used && ipsec_in_reject(m, last)) { 201 /* do not inject data into pcb */ 202 } 203 #endif 204 else if ((n = m_copypacket(m, M_DONTWAIT)) != NULL) { 205 rip_sbappendaddr(last, ip, sintosa(&ripsrc), hlen, n); 206 } 207 208 last = inp; 209 } 210 211 #if defined(IPSEC) 212 if (ipsec_used && last != NULL && ipsec_in_reject(m, last)) { 213 m_freem(m); 214 IP_STATDEC(IP_STAT_DELIVERED); 215 /* do not inject data into pcb */ 216 } else 217 #endif 218 if (last != NULL) { 219 rip_sbappendaddr(last, ip, sintosa(&ripsrc), hlen, m); 220 } else if (inetsw[ip_protox[ip->ip_p]].pr_input == rip_input) { 221 net_stat_ref_t ips; 222 223 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PROTOCOL, 224 0, 0); 225 ips = IP_STAT_GETREF(); 226 _NET_STATINC_REF(ips, IP_STAT_NOPROTO); 227 _NET_STATDEC_REF(ips, IP_STAT_DELIVERED); 228 IP_STAT_PUTREF(); 229 } else { 230 m_freem(m); 231 } 232 233 return; 234 } 235 236 int 237 rip_pcbnotify(struct inpcbtable *table, 238 struct in_addr faddr, struct in_addr laddr, int proto, int errno, 239 void (*notify)(struct inpcb *, int)) 240 { 241 struct inpcb *inp; 242 int nmatch; 243 244 nmatch = 0; 245 TAILQ_FOREACH(inp, &table->inpt_queue, inp_queue) { 246 if (inp->inp_af != AF_INET) 247 continue; 248 if (in4p_ip(inp).ip_p && in4p_ip(inp).ip_p != proto) 249 continue; 250 if (in_hosteq(in4p_faddr(inp), faddr) && 251 in_hosteq(in4p_laddr(inp), laddr)) { 252 (*notify)(inp, errno); 253 nmatch++; 254 } 255 } 256 257 return nmatch; 258 } 259 260 void * 261 rip_ctlinput(int cmd, const struct sockaddr *sa, void *v) 262 { 263 struct ip *ip = v; 264 void (*notify)(struct inpcb *, int) = inpcb_rtchange; 265 int errno; 266 267 if (sa->sa_family != AF_INET || 268 sa->sa_len != sizeof(struct sockaddr_in)) 269 return NULL; 270 if ((unsigned)cmd >= PRC_NCMDS) 271 return NULL; 272 errno = inetctlerrmap[cmd]; 273 if (PRC_IS_REDIRECT(cmd)) 274 notify = inpcb_rtchange, ip = 0; 275 else if (cmd == PRC_HOSTDEAD) 276 ip = 0; 277 else if (errno == 0) 278 return NULL; 279 if (ip) { 280 rip_pcbnotify(&rawcbtable, satocsin(sa)->sin_addr, 281 ip->ip_src, ip->ip_p, errno, notify); 282 283 /* XXX mapped address case */ 284 } else 285 inpcb_notifyall(&rawcbtable, satocsin(sa)->sin_addr, errno, 286 notify); 287 return NULL; 288 } 289 290 /* 291 * Generate IP header and pass packet to ip_output. 292 * Tack on options user may have setup with control call. 293 */ 294 int 295 rip_output(struct mbuf *m, struct inpcb *inp, struct mbuf *control, 296 struct lwp *l) 297 { 298 struct ip *ip; 299 struct mbuf *opts; 300 struct ip_pktopts pktopts; 301 kauth_cred_t cred; 302 int error, flags; 303 304 flags = (inp->inp_socket->so_options & SO_DONTROUTE) | 305 IP_ALLOWBROADCAST | IP_RETURNMTU; 306 307 if (l == NULL) 308 cred = NULL; 309 else 310 cred = l->l_cred; 311 312 /* Setup IP outgoing packet options */ 313 memset(&pktopts, 0, sizeof(pktopts)); 314 error = ip_setpktopts(control, &pktopts, &flags, inp, cred); 315 m_freem(control); 316 if (error != 0) 317 goto release; 318 319 /* 320 * If the user handed us a complete IP packet, use it. 321 * Otherwise, allocate an mbuf for a header and fill it in. 322 */ 323 if ((inp->inp_flags & INP_HDRINCL) == 0) { 324 if ((m->m_pkthdr.len + sizeof(struct ip)) > IP_MAXPACKET) { 325 error = EMSGSIZE; 326 goto release; 327 } 328 M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); 329 if (!m) { 330 error = ENOBUFS; 331 goto release; 332 } 333 ip = mtod(m, struct ip *); 334 ip->ip_tos = 0; 335 ip->ip_off = htons(0); 336 ip->ip_p = in4p_ip(inp).ip_p; 337 ip->ip_len = htons(m->m_pkthdr.len); 338 ip->ip_src = pktopts.ippo_laddr.sin_addr; 339 ip->ip_dst = in4p_faddr(inp); 340 ip->ip_ttl = MAXTTL; 341 opts = inp->inp_options; 342 } else { 343 if (m->m_pkthdr.len > IP_MAXPACKET) { 344 error = EMSGSIZE; 345 goto release; 346 } 347 if (m->m_pkthdr.len < sizeof(struct ip)) { 348 error = EINVAL; 349 goto release; 350 } 351 ip = mtod(m, struct ip *); 352 353 /* 354 * If the mbuf is read-only, we need to allocate 355 * a new mbuf for the header, since we need to 356 * modify the header. 357 */ 358 if (M_READONLY(m)) { 359 int hlen = ip->ip_hl << 2; 360 361 m = m_copyup(m, hlen, (max_linkhdr + 3) & ~3); 362 if (m == NULL) { 363 error = ENOMEM; 364 goto release; 365 } 366 ip = mtod(m, struct ip *); 367 } 368 369 /* XXX userland passes ip_len and ip_off in host order */ 370 if (m->m_pkthdr.len != ip->ip_len) { 371 error = EINVAL; 372 goto release; 373 } 374 HTONS(ip->ip_len); 375 HTONS(ip->ip_off); 376 377 if (ip->ip_id != 0 || m->m_pkthdr.len < IP_MINFRAGSIZE) 378 flags |= IP_NOIPNEWID; 379 opts = NULL; 380 381 /* Prevent ip_output from overwriting header fields. */ 382 flags |= IP_RAWOUTPUT; 383 384 IP_STATINC(IP_STAT_RAWOUT); 385 } 386 387 /* 388 * IP output. Note: if IP_RETURNMTU flag is set, the MTU size 389 * will be stored in inp_errormtu. 390 */ 391 return ip_output(m, opts, &inp->inp_route, flags, pktopts.ippo_imo, 392 inp); 393 394 release: 395 m_freem(m); 396 return error; 397 } 398 399 /* 400 * Raw IP socket option processing. 401 */ 402 int 403 rip_ctloutput(int op, struct socket *so, struct sockopt *sopt) 404 { 405 struct inpcb *inp = sotoinpcb(so); 406 int error = 0; 407 int optval; 408 409 if (sopt->sopt_level == SOL_SOCKET && sopt->sopt_name == SO_NOHEADER) { 410 if (op == PRCO_GETOPT) { 411 optval = (inp->inp_flags & INP_NOHEADER) ? 1 : 0; 412 error = sockopt_set(sopt, &optval, sizeof(optval)); 413 } else if (op == PRCO_SETOPT) { 414 error = sockopt_getint(sopt, &optval); 415 if (error) 416 goto out; 417 if (optval) { 418 inp->inp_flags &= ~INP_HDRINCL; 419 inp->inp_flags |= INP_NOHEADER; 420 } else 421 inp->inp_flags &= ~INP_NOHEADER; 422 } 423 goto out; 424 } else if (sopt->sopt_level != IPPROTO_IP) 425 return ip_ctloutput(op, so, sopt); 426 427 switch (op) { 428 429 case PRCO_SETOPT: 430 switch (sopt->sopt_name) { 431 case IP_HDRINCL: 432 error = sockopt_getint(sopt, &optval); 433 if (error) 434 break; 435 if (optval) 436 inp->inp_flags |= INP_HDRINCL; 437 else 438 inp->inp_flags &= ~INP_HDRINCL; 439 break; 440 441 #ifdef MROUTING 442 case MRT_INIT: 443 case MRT_DONE: 444 case MRT_ADD_VIF: 445 case MRT_DEL_VIF: 446 case MRT_ADD_MFC: 447 case MRT_DEL_MFC: 448 case MRT_ASSERT: 449 case MRT_API_CONFIG: 450 case MRT_ADD_BW_UPCALL: 451 case MRT_DEL_BW_UPCALL: 452 error = ip_mrouter_set(so, sopt); 453 break; 454 #endif 455 456 default: 457 error = ip_ctloutput(op, so, sopt); 458 break; 459 } 460 break; 461 462 case PRCO_GETOPT: 463 switch (sopt->sopt_name) { 464 case IP_HDRINCL: 465 optval = inp->inp_flags & INP_HDRINCL; 466 error = sockopt_set(sopt, &optval, sizeof(optval)); 467 break; 468 469 #ifdef MROUTING 470 case MRT_VERSION: 471 case MRT_ASSERT: 472 case MRT_API_SUPPORT: 473 case MRT_API_CONFIG: 474 error = ip_mrouter_get(so, sopt); 475 break; 476 #endif 477 478 default: 479 error = ip_ctloutput(op, so, sopt); 480 break; 481 } 482 break; 483 } 484 out: 485 return error; 486 } 487 488 int 489 rip_connect_pcb(struct inpcb *inp, struct sockaddr_in *addr) 490 { 491 492 if (IFNET_READER_EMPTY()) 493 return (EADDRNOTAVAIL); 494 if (addr->sin_family != AF_INET) 495 return (EAFNOSUPPORT); 496 if (addr->sin_len != sizeof(*addr)) 497 return EINVAL; 498 in4p_faddr(inp) = addr->sin_addr; 499 return (0); 500 } 501 502 static void 503 rip_disconnect1(struct inpcb *inp) 504 { 505 506 in4p_faddr(inp) = zeroin_addr; 507 } 508 509 static int 510 rip_attach(struct socket *so, int proto) 511 { 512 struct inpcb *inp; 513 int error; 514 515 KASSERT(sotoinpcb(so) == NULL); 516 sosetlock(so); 517 518 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { 519 error = soreserve(so, rip_sendspace, rip_recvspace); 520 if (error) { 521 return error; 522 } 523 } 524 525 error = inpcb_create(so, &rawcbtable); 526 if (error) { 527 return error; 528 } 529 inp = sotoinpcb(so); 530 in4p_ip(inp).ip_p = proto; 531 KASSERT(solocked(so)); 532 533 return 0; 534 } 535 536 static void 537 rip_detach(struct socket *so) 538 { 539 struct inpcb *inp; 540 541 KASSERT(solocked(so)); 542 inp = sotoinpcb(so); 543 KASSERT(inp != NULL); 544 545 #ifdef MROUTING 546 extern struct socket *ip_mrouter; 547 if (so == ip_mrouter) { 548 ip_mrouter_done(); 549 } 550 #endif 551 inpcb_destroy(inp); 552 } 553 554 static int 555 rip_accept(struct socket *so, struct sockaddr *nam) 556 { 557 KASSERT(solocked(so)); 558 559 panic("rip_accept"); 560 561 return EOPNOTSUPP; 562 } 563 564 static int 565 rip_bind(struct socket *so, struct sockaddr *nam, struct lwp *l) 566 { 567 struct inpcb *inp = sotoinpcb(so); 568 struct sockaddr_in *addr = (struct sockaddr_in *)nam; 569 int error = 0; 570 int s, ss; 571 struct ifaddr *ifa; 572 573 KASSERT(solocked(so)); 574 KASSERT(inp != NULL); 575 KASSERT(nam != NULL); 576 577 if (addr->sin_len != sizeof(*addr)) 578 return EINVAL; 579 580 s = splsoftnet(); 581 if (IFNET_READER_EMPTY()) { 582 error = EADDRNOTAVAIL; 583 goto release; 584 } 585 if (addr->sin_family != AF_INET) { 586 error = EAFNOSUPPORT; 587 goto release; 588 } 589 ss = pserialize_read_enter(); 590 if ((ifa = ifa_ifwithaddr(sintosa(addr))) == NULL && 591 (inp->inp_flags & INP_BINDANY) == 0 && 592 !in_nullhost(addr->sin_addr)) 593 { 594 pserialize_read_exit(ss); 595 error = EADDRNOTAVAIL; 596 goto release; 597 } 598 if (ifa && (ifatoia(ifa))->ia4_flags & IN6_IFF_DUPLICATED) { 599 pserialize_read_exit(ss); 600 error = EADDRNOTAVAIL; 601 goto release; 602 } 603 pserialize_read_exit(ss); 604 605 in4p_laddr(inp) = addr->sin_addr; 606 607 release: 608 splx(s); 609 return error; 610 } 611 612 static int 613 rip_listen(struct socket *so, struct lwp *l) 614 { 615 KASSERT(solocked(so)); 616 617 return EOPNOTSUPP; 618 } 619 620 static int 621 rip_connect(struct socket *so, struct sockaddr *nam, struct lwp *l) 622 { 623 struct inpcb *inp = sotoinpcb(so); 624 int error = 0; 625 int s; 626 627 KASSERT(solocked(so)); 628 KASSERT(inp != NULL); 629 KASSERT(nam != NULL); 630 631 s = splsoftnet(); 632 error = rip_connect_pcb(inp, (struct sockaddr_in *)nam); 633 if (! error) 634 soisconnected(so); 635 splx(s); 636 637 return error; 638 } 639 640 static int 641 rip_connect2(struct socket *so, struct socket *so2) 642 { 643 KASSERT(solocked(so)); 644 645 return EOPNOTSUPP; 646 } 647 648 static int 649 rip_disconnect(struct socket *so) 650 { 651 struct inpcb *inp = sotoinpcb(so); 652 int s; 653 654 KASSERT(solocked(so)); 655 KASSERT(inp != NULL); 656 657 s = splsoftnet(); 658 soisdisconnected(so); 659 rip_disconnect1(inp); 660 splx(s); 661 662 return 0; 663 } 664 665 static int 666 rip_shutdown(struct socket *so) 667 { 668 int s; 669 670 KASSERT(solocked(so)); 671 672 /* 673 * Mark the connection as being incapable of further input. 674 */ 675 s = splsoftnet(); 676 socantsendmore(so); 677 splx(s); 678 679 return 0; 680 } 681 682 static int 683 rip_abort(struct socket *so) 684 { 685 KASSERT(solocked(so)); 686 687 panic("rip_abort"); 688 689 return EOPNOTSUPP; 690 } 691 692 static int 693 rip_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp) 694 { 695 return in_control(so, cmd, nam, ifp); 696 } 697 698 static int 699 rip_stat(struct socket *so, struct stat *ub) 700 { 701 KASSERT(solocked(so)); 702 703 /* stat: don't bother with a blocksize. */ 704 return 0; 705 } 706 707 static int 708 rip_peeraddr(struct socket *so, struct sockaddr *nam) 709 { 710 int s; 711 712 KASSERT(solocked(so)); 713 KASSERT(sotoinpcb(so) != NULL); 714 KASSERT(nam != NULL); 715 716 s = splsoftnet(); 717 inpcb_fetch_peeraddr(sotoinpcb(so), (struct sockaddr_in *)nam); 718 splx(s); 719 720 return 0; 721 } 722 723 static int 724 rip_sockaddr(struct socket *so, struct sockaddr *nam) 725 { 726 int s; 727 728 KASSERT(solocked(so)); 729 KASSERT(sotoinpcb(so) != NULL); 730 KASSERT(nam != NULL); 731 732 s = splsoftnet(); 733 inpcb_fetch_sockaddr(sotoinpcb(so), (struct sockaddr_in *)nam); 734 splx(s); 735 736 return 0; 737 } 738 739 static int 740 rip_rcvd(struct socket *so, int flags, struct lwp *l) 741 { 742 KASSERT(solocked(so)); 743 744 return EOPNOTSUPP; 745 } 746 747 static int 748 rip_recvoob(struct socket *so, struct mbuf *m, int flags) 749 { 750 KASSERT(solocked(so)); 751 752 return EOPNOTSUPP; 753 } 754 755 static int 756 rip_send(struct socket *so, struct mbuf *m, struct sockaddr *nam, 757 struct mbuf *control, struct lwp *l) 758 { 759 struct inpcb *inp = sotoinpcb(so); 760 int error = 0; 761 int s; 762 763 KASSERT(solocked(so)); 764 KASSERT(inp != NULL); 765 KASSERT(m != NULL); 766 767 /* 768 * Ship a packet out. The appropriate raw output 769 * routine handles any massaging necessary. 770 */ 771 s = splsoftnet(); 772 if (nam) { 773 if ((so->so_state & SS_ISCONNECTED) != 0) { 774 error = EISCONN; 775 goto die; 776 } 777 error = rip_connect_pcb(inp, (struct sockaddr_in *)nam); 778 if (error) 779 goto die; 780 } else { 781 if ((so->so_state & SS_ISCONNECTED) == 0) { 782 error = ENOTCONN; 783 goto die; 784 } 785 } 786 error = rip_output(m, inp, control, l); 787 m = NULL; 788 control = NULL; 789 if (nam) 790 rip_disconnect1(inp); 791 die: 792 m_freem(m); 793 m_freem(control); 794 795 splx(s); 796 return error; 797 } 798 799 static int 800 rip_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control) 801 { 802 KASSERT(solocked(so)); 803 804 m_freem(m); 805 m_freem(control); 806 807 return EOPNOTSUPP; 808 } 809 810 static int 811 rip_purgeif(struct socket *so, struct ifnet *ifp) 812 { 813 int s; 814 815 s = splsoftnet(); 816 mutex_enter(softnet_lock); 817 inpcb_purgeif0(&rawcbtable, ifp); 818 #ifdef NET_MPSAFE 819 mutex_exit(softnet_lock); 820 #endif 821 in_purgeif(ifp); 822 #ifdef NET_MPSAFE 823 mutex_enter(softnet_lock); 824 #endif 825 inpcb_purgeif(&rawcbtable, ifp); 826 mutex_exit(softnet_lock); 827 splx(s); 828 829 return 0; 830 } 831 832 PR_WRAP_USRREQS(rip) 833 #define rip_attach rip_attach_wrapper 834 #define rip_detach rip_detach_wrapper 835 #define rip_accept rip_accept_wrapper 836 #define rip_bind rip_bind_wrapper 837 #define rip_listen rip_listen_wrapper 838 #define rip_connect rip_connect_wrapper 839 #define rip_connect2 rip_connect2_wrapper 840 #define rip_disconnect rip_disconnect_wrapper 841 #define rip_shutdown rip_shutdown_wrapper 842 #define rip_abort rip_abort_wrapper 843 #define rip_ioctl rip_ioctl_wrapper 844 #define rip_stat rip_stat_wrapper 845 #define rip_peeraddr rip_peeraddr_wrapper 846 #define rip_sockaddr rip_sockaddr_wrapper 847 #define rip_rcvd rip_rcvd_wrapper 848 #define rip_recvoob rip_recvoob_wrapper 849 #define rip_send rip_send_wrapper 850 #define rip_sendoob rip_sendoob_wrapper 851 #define rip_purgeif rip_purgeif_wrapper 852 853 const struct pr_usrreqs rip_usrreqs = { 854 .pr_attach = rip_attach, 855 .pr_detach = rip_detach, 856 .pr_accept = rip_accept, 857 .pr_bind = rip_bind, 858 .pr_listen = rip_listen, 859 .pr_connect = rip_connect, 860 .pr_connect2 = rip_connect2, 861 .pr_disconnect = rip_disconnect, 862 .pr_shutdown = rip_shutdown, 863 .pr_abort = rip_abort, 864 .pr_ioctl = rip_ioctl, 865 .pr_stat = rip_stat, 866 .pr_peeraddr = rip_peeraddr, 867 .pr_sockaddr = rip_sockaddr, 868 .pr_rcvd = rip_rcvd, 869 .pr_recvoob = rip_recvoob, 870 .pr_send = rip_send, 871 .pr_sendoob = rip_sendoob, 872 .pr_purgeif = rip_purgeif, 873 }; 874 875 static void 876 sysctl_net_inet_raw_setup(struct sysctllog **clog) 877 { 878 879 sysctl_createv(clog, 0, NULL, NULL, 880 CTLFLAG_PERMANENT, 881 CTLTYPE_NODE, "inet", NULL, 882 NULL, 0, NULL, 0, 883 CTL_NET, PF_INET, CTL_EOL); 884 sysctl_createv(clog, 0, NULL, NULL, 885 CTLFLAG_PERMANENT, 886 CTLTYPE_NODE, "raw", 887 SYSCTL_DESCR("Raw IPv4 settings"), 888 NULL, 0, NULL, 0, 889 CTL_NET, PF_INET, IPPROTO_RAW, CTL_EOL); 890 891 sysctl_createv(clog, 0, NULL, NULL, 892 CTLFLAG_PERMANENT, 893 CTLTYPE_STRUCT, "pcblist", 894 SYSCTL_DESCR("Raw IPv4 control block list"), 895 sysctl_inpcblist, 0, &rawcbtable, 0, 896 CTL_NET, PF_INET, IPPROTO_RAW, 897 CTL_CREATE, CTL_EOL); 898 } 899