1 /* $NetBSD: raw_ip.c,v 1.180 2020/09/08 14:12:57 christos 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.180 2020/09/08 14:12:57 christos 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 in_pcbinit(&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 if (opts) 153 m_freem(opts); 154 } else { 155 sorwakeup(last->inp_socket); 156 } 157 } 158 159 /* 160 * Setup generic address and protocol structures 161 * for raw_input routine, then pass them along with 162 * mbuf chain. 163 */ 164 void 165 rip_input(struct mbuf *m, int off, int proto) 166 { 167 struct ip *ip = mtod(m, struct ip *); 168 struct inpcb_hdr *inph; 169 struct inpcb *inp; 170 struct inpcb *last = NULL; 171 struct mbuf *n; 172 struct sockaddr_in ripsrc; 173 int hlen; 174 175 sockaddr_in_init(&ripsrc, &ip->ip_src, 0); 176 177 /* 178 * XXX Compatibility: programs using raw IP expect ip_len 179 * XXX to have the header length subtracted, and in host order. 180 * XXX ip_off is also expected to be host order. 181 */ 182 hlen = ip->ip_hl << 2; 183 ip->ip_len = ntohs(ip->ip_len) - hlen; 184 NTOHS(ip->ip_off); 185 186 TAILQ_FOREACH(inph, &rawcbtable.inpt_queue, inph_queue) { 187 inp = (struct inpcb *)inph; 188 if (inp->inp_af != AF_INET) 189 continue; 190 if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != proto) 191 continue; 192 if (!in_nullhost(inp->inp_laddr) && 193 !in_hosteq(inp->inp_laddr, ip->ip_dst)) 194 continue; 195 if (!in_nullhost(inp->inp_faddr) && 196 !in_hosteq(inp->inp_faddr, ip->ip_src)) 197 continue; 198 199 if (last == NULL) { 200 ; 201 } 202 #if defined(IPSEC) 203 else if (ipsec_used && ipsec_in_reject(m, last)) { 204 /* do not inject data into pcb */ 205 } 206 #endif 207 else if ((n = m_copypacket(m, M_DONTWAIT)) != NULL) { 208 rip_sbappendaddr(last, ip, sintosa(&ripsrc), hlen, n); 209 } 210 211 last = inp; 212 } 213 214 #if defined(IPSEC) 215 if (ipsec_used && last != NULL && ipsec_in_reject(m, last)) { 216 m_freem(m); 217 IP_STATDEC(IP_STAT_DELIVERED); 218 /* do not inject data into pcb */ 219 } else 220 #endif 221 if (last != NULL) { 222 rip_sbappendaddr(last, ip, sintosa(&ripsrc), hlen, m); 223 } else if (inetsw[ip_protox[ip->ip_p]].pr_input == rip_input) { 224 uint64_t *ips; 225 226 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PROTOCOL, 227 0, 0); 228 ips = IP_STAT_GETREF(); 229 ips[IP_STAT_NOPROTO]++; 230 ips[IP_STAT_DELIVERED]--; 231 IP_STAT_PUTREF(); 232 } else { 233 m_freem(m); 234 } 235 236 return; 237 } 238 239 int 240 rip_pcbnotify(struct inpcbtable *table, 241 struct in_addr faddr, struct in_addr laddr, int proto, int errno, 242 void (*notify)(struct inpcb *, int)) 243 { 244 struct inpcb_hdr *inph, *ninph; 245 int nmatch; 246 247 nmatch = 0; 248 TAILQ_FOREACH_SAFE(inph, &table->inpt_queue, inph_queue, ninph) { 249 struct inpcb *inp = (struct inpcb *)inph; 250 if (inp->inp_af != AF_INET) 251 continue; 252 if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != proto) 253 continue; 254 if (in_hosteq(inp->inp_faddr, faddr) && 255 in_hosteq(inp->inp_laddr, laddr)) { 256 (*notify)(inp, errno); 257 nmatch++; 258 } 259 } 260 261 return nmatch; 262 } 263 264 void * 265 rip_ctlinput(int cmd, const struct sockaddr *sa, void *v) 266 { 267 struct ip *ip = v; 268 void (*notify)(struct inpcb *, int) = in_rtchange; 269 int errno; 270 271 if (sa->sa_family != AF_INET || 272 sa->sa_len != sizeof(struct sockaddr_in)) 273 return NULL; 274 if ((unsigned)cmd >= PRC_NCMDS) 275 return NULL; 276 errno = inetctlerrmap[cmd]; 277 if (PRC_IS_REDIRECT(cmd)) 278 notify = in_rtchange, ip = 0; 279 else if (cmd == PRC_HOSTDEAD) 280 ip = 0; 281 else if (errno == 0) 282 return NULL; 283 if (ip) { 284 rip_pcbnotify(&rawcbtable, satocsin(sa)->sin_addr, 285 ip->ip_src, ip->ip_p, errno, notify); 286 287 /* XXX mapped address case */ 288 } else 289 in_pcbnotifyall(&rawcbtable, satocsin(sa)->sin_addr, errno, 290 notify); 291 return NULL; 292 } 293 294 /* 295 * Generate IP header and pass packet to ip_output. 296 * Tack on options user may have setup with control call. 297 */ 298 int 299 rip_output(struct mbuf *m, struct inpcb *inp, struct mbuf *control, 300 struct lwp *l) 301 { 302 struct ip *ip; 303 struct mbuf *opts; 304 struct ip_pktopts pktopts; 305 kauth_cred_t cred; 306 int error, flags; 307 308 flags = (inp->inp_socket->so_options & SO_DONTROUTE) | 309 IP_ALLOWBROADCAST | IP_RETURNMTU; 310 311 if (l == NULL) 312 cred = NULL; 313 else 314 cred = l->l_cred; 315 316 /* Setup IP outgoing packet options */ 317 memset(&pktopts, 0, sizeof(pktopts)); 318 error = ip_setpktopts(control, &pktopts, &flags, inp, cred); 319 if (control != NULL) 320 m_freem(control); 321 if (error != 0) 322 goto release; 323 324 /* 325 * If the user handed us a complete IP packet, use it. 326 * Otherwise, allocate an mbuf for a header and fill it in. 327 */ 328 if ((inp->inp_flags & INP_HDRINCL) == 0) { 329 if ((m->m_pkthdr.len + sizeof(struct ip)) > IP_MAXPACKET) { 330 error = EMSGSIZE; 331 goto release; 332 } 333 M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); 334 if (!m) { 335 error = ENOBUFS; 336 goto release; 337 } 338 ip = mtod(m, struct ip *); 339 ip->ip_tos = 0; 340 ip->ip_off = htons(0); 341 ip->ip_p = inp->inp_ip.ip_p; 342 ip->ip_len = htons(m->m_pkthdr.len); 343 ip->ip_src = pktopts.ippo_laddr.sin_addr; 344 ip->ip_dst = inp->inp_faddr; 345 ip->ip_ttl = MAXTTL; 346 opts = inp->inp_options; 347 } else { 348 if (m->m_pkthdr.len > IP_MAXPACKET) { 349 error = EMSGSIZE; 350 goto release; 351 } 352 if (m->m_pkthdr.len < sizeof(struct ip)) { 353 error = EINVAL; 354 goto release; 355 } 356 ip = mtod(m, struct ip *); 357 358 /* 359 * If the mbuf is read-only, we need to allocate 360 * a new mbuf for the header, since we need to 361 * modify the header. 362 */ 363 if (M_READONLY(m)) { 364 int hlen = ip->ip_hl << 2; 365 366 m = m_copyup(m, hlen, (max_linkhdr + 3) & ~3); 367 if (m == NULL) { 368 error = ENOMEM; 369 goto release; 370 } 371 ip = mtod(m, struct ip *); 372 } 373 374 /* XXX userland passes ip_len and ip_off in host order */ 375 if (m->m_pkthdr.len != ip->ip_len) { 376 error = EINVAL; 377 goto release; 378 } 379 HTONS(ip->ip_len); 380 HTONS(ip->ip_off); 381 382 if (ip->ip_id != 0 || m->m_pkthdr.len < IP_MINFRAGSIZE) 383 flags |= IP_NOIPNEWID; 384 opts = NULL; 385 386 /* Prevent ip_output from overwriting header fields. */ 387 flags |= IP_RAWOUTPUT; 388 389 IP_STATINC(IP_STAT_RAWOUT); 390 } 391 392 /* 393 * IP output. Note: if IP_RETURNMTU flag is set, the MTU size 394 * will be stored in inp_errormtu. 395 */ 396 return ip_output(m, opts, &inp->inp_route, flags, pktopts.ippo_imo, 397 inp); 398 399 release: 400 if (m != NULL) 401 m_freem(m); 402 return error; 403 } 404 405 /* 406 * Raw IP socket option processing. 407 */ 408 int 409 rip_ctloutput(int op, struct socket *so, struct sockopt *sopt) 410 { 411 struct inpcb *inp = sotoinpcb(so); 412 int error = 0; 413 int optval; 414 415 if (sopt->sopt_level == SOL_SOCKET && sopt->sopt_name == SO_NOHEADER) { 416 if (op == PRCO_GETOPT) { 417 optval = (inp->inp_flags & INP_NOHEADER) ? 1 : 0; 418 error = sockopt_set(sopt, &optval, sizeof(optval)); 419 } else if (op == PRCO_SETOPT) { 420 error = sockopt_getint(sopt, &optval); 421 if (error) 422 goto out; 423 if (optval) { 424 inp->inp_flags &= ~INP_HDRINCL; 425 inp->inp_flags |= INP_NOHEADER; 426 } else 427 inp->inp_flags &= ~INP_NOHEADER; 428 } 429 goto out; 430 } else if (sopt->sopt_level != IPPROTO_IP) 431 return ip_ctloutput(op, so, sopt); 432 433 switch (op) { 434 435 case PRCO_SETOPT: 436 switch (sopt->sopt_name) { 437 case IP_HDRINCL: 438 error = sockopt_getint(sopt, &optval); 439 if (error) 440 break; 441 if (optval) 442 inp->inp_flags |= INP_HDRINCL; 443 else 444 inp->inp_flags &= ~INP_HDRINCL; 445 break; 446 447 #ifdef MROUTING 448 case MRT_INIT: 449 case MRT_DONE: 450 case MRT_ADD_VIF: 451 case MRT_DEL_VIF: 452 case MRT_ADD_MFC: 453 case MRT_DEL_MFC: 454 case MRT_ASSERT: 455 case MRT_API_CONFIG: 456 case MRT_ADD_BW_UPCALL: 457 case MRT_DEL_BW_UPCALL: 458 error = ip_mrouter_set(so, sopt); 459 break; 460 #endif 461 462 default: 463 error = ip_ctloutput(op, so, sopt); 464 break; 465 } 466 break; 467 468 case PRCO_GETOPT: 469 switch (sopt->sopt_name) { 470 case IP_HDRINCL: 471 optval = inp->inp_flags & INP_HDRINCL; 472 error = sockopt_set(sopt, &optval, sizeof(optval)); 473 break; 474 475 #ifdef MROUTING 476 case MRT_VERSION: 477 case MRT_ASSERT: 478 case MRT_API_SUPPORT: 479 case MRT_API_CONFIG: 480 error = ip_mrouter_get(so, sopt); 481 break; 482 #endif 483 484 default: 485 error = ip_ctloutput(op, so, sopt); 486 break; 487 } 488 break; 489 } 490 out: 491 return error; 492 } 493 494 int 495 rip_connect_pcb(struct inpcb *inp, struct sockaddr_in *addr) 496 { 497 498 if (IFNET_READER_EMPTY()) 499 return (EADDRNOTAVAIL); 500 if (addr->sin_family != AF_INET) 501 return (EAFNOSUPPORT); 502 if (addr->sin_len != sizeof(*addr)) 503 return EINVAL; 504 inp->inp_faddr = addr->sin_addr; 505 return (0); 506 } 507 508 static void 509 rip_disconnect1(struct inpcb *inp) 510 { 511 512 inp->inp_faddr = zeroin_addr; 513 } 514 515 static int 516 rip_attach(struct socket *so, int proto) 517 { 518 struct inpcb *inp; 519 int error; 520 521 KASSERT(sotoinpcb(so) == NULL); 522 sosetlock(so); 523 524 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { 525 error = soreserve(so, rip_sendspace, rip_recvspace); 526 if (error) { 527 return error; 528 } 529 } 530 531 error = in_pcballoc(so, &rawcbtable); 532 if (error) { 533 return error; 534 } 535 inp = sotoinpcb(so); 536 inp->inp_ip.ip_p = proto; 537 KASSERT(solocked(so)); 538 539 return 0; 540 } 541 542 static void 543 rip_detach(struct socket *so) 544 { 545 struct inpcb *inp; 546 547 KASSERT(solocked(so)); 548 inp = sotoinpcb(so); 549 KASSERT(inp != NULL); 550 551 #ifdef MROUTING 552 extern struct socket *ip_mrouter; 553 if (so == ip_mrouter) { 554 ip_mrouter_done(); 555 } 556 #endif 557 in_pcbdetach(inp); 558 } 559 560 static int 561 rip_accept(struct socket *so, struct sockaddr *nam) 562 { 563 KASSERT(solocked(so)); 564 565 panic("rip_accept"); 566 567 return EOPNOTSUPP; 568 } 569 570 static int 571 rip_bind(struct socket *so, struct sockaddr *nam, struct lwp *l) 572 { 573 struct inpcb *inp = sotoinpcb(so); 574 struct sockaddr_in *addr = (struct sockaddr_in *)nam; 575 int error = 0; 576 int s, ss; 577 struct ifaddr *ifa; 578 579 KASSERT(solocked(so)); 580 KASSERT(inp != NULL); 581 KASSERT(nam != NULL); 582 583 if (addr->sin_len != sizeof(*addr)) 584 return EINVAL; 585 586 s = splsoftnet(); 587 if (IFNET_READER_EMPTY()) { 588 error = EADDRNOTAVAIL; 589 goto release; 590 } 591 if (addr->sin_family != AF_INET) { 592 error = EAFNOSUPPORT; 593 goto release; 594 } 595 ss = pserialize_read_enter(); 596 if ((ifa = ifa_ifwithaddr(sintosa(addr))) == NULL && 597 (inp->inp_flags & INP_BINDANY) == 0 && 598 !in_nullhost(addr->sin_addr)) 599 { 600 pserialize_read_exit(ss); 601 error = EADDRNOTAVAIL; 602 goto release; 603 } 604 if (ifa && (ifatoia(ifa))->ia4_flags & IN6_IFF_DUPLICATED) { 605 pserialize_read_exit(ss); 606 error = EADDRNOTAVAIL; 607 goto release; 608 } 609 pserialize_read_exit(ss); 610 611 inp->inp_laddr = addr->sin_addr; 612 613 release: 614 splx(s); 615 return error; 616 } 617 618 static int 619 rip_listen(struct socket *so, struct lwp *l) 620 { 621 KASSERT(solocked(so)); 622 623 return EOPNOTSUPP; 624 } 625 626 static int 627 rip_connect(struct socket *so, struct sockaddr *nam, struct lwp *l) 628 { 629 struct inpcb *inp = sotoinpcb(so); 630 int error = 0; 631 int s; 632 633 KASSERT(solocked(so)); 634 KASSERT(inp != NULL); 635 KASSERT(nam != NULL); 636 637 s = splsoftnet(); 638 error = rip_connect_pcb(inp, (struct sockaddr_in *)nam); 639 if (! error) 640 soisconnected(so); 641 splx(s); 642 643 return error; 644 } 645 646 static int 647 rip_connect2(struct socket *so, struct socket *so2) 648 { 649 KASSERT(solocked(so)); 650 651 return EOPNOTSUPP; 652 } 653 654 static int 655 rip_disconnect(struct socket *so) 656 { 657 struct inpcb *inp = sotoinpcb(so); 658 int s; 659 660 KASSERT(solocked(so)); 661 KASSERT(inp != NULL); 662 663 s = splsoftnet(); 664 soisdisconnected(so); 665 rip_disconnect1(inp); 666 splx(s); 667 668 return 0; 669 } 670 671 static int 672 rip_shutdown(struct socket *so) 673 { 674 int s; 675 676 KASSERT(solocked(so)); 677 678 /* 679 * Mark the connection as being incapable of further input. 680 */ 681 s = splsoftnet(); 682 socantsendmore(so); 683 splx(s); 684 685 return 0; 686 } 687 688 static int 689 rip_abort(struct socket *so) 690 { 691 KASSERT(solocked(so)); 692 693 panic("rip_abort"); 694 695 return EOPNOTSUPP; 696 } 697 698 static int 699 rip_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp) 700 { 701 return in_control(so, cmd, nam, ifp); 702 } 703 704 static int 705 rip_stat(struct socket *so, struct stat *ub) 706 { 707 KASSERT(solocked(so)); 708 709 /* stat: don't bother with a blocksize. */ 710 return 0; 711 } 712 713 static int 714 rip_peeraddr(struct socket *so, struct sockaddr *nam) 715 { 716 int s; 717 718 KASSERT(solocked(so)); 719 KASSERT(sotoinpcb(so) != NULL); 720 KASSERT(nam != NULL); 721 722 s = splsoftnet(); 723 in_setpeeraddr(sotoinpcb(so), (struct sockaddr_in *)nam); 724 splx(s); 725 726 return 0; 727 } 728 729 static int 730 rip_sockaddr(struct socket *so, struct sockaddr *nam) 731 { 732 int s; 733 734 KASSERT(solocked(so)); 735 KASSERT(sotoinpcb(so) != NULL); 736 KASSERT(nam != NULL); 737 738 s = splsoftnet(); 739 in_setsockaddr(sotoinpcb(so), (struct sockaddr_in *)nam); 740 splx(s); 741 742 return 0; 743 } 744 745 static int 746 rip_rcvd(struct socket *so, int flags, struct lwp *l) 747 { 748 KASSERT(solocked(so)); 749 750 return EOPNOTSUPP; 751 } 752 753 static int 754 rip_recvoob(struct socket *so, struct mbuf *m, int flags) 755 { 756 KASSERT(solocked(so)); 757 758 return EOPNOTSUPP; 759 } 760 761 static int 762 rip_send(struct socket *so, struct mbuf *m, struct sockaddr *nam, 763 struct mbuf *control, struct lwp *l) 764 { 765 struct inpcb *inp = sotoinpcb(so); 766 int error = 0; 767 int s; 768 769 KASSERT(solocked(so)); 770 KASSERT(inp != NULL); 771 KASSERT(m != NULL); 772 773 /* 774 * Ship a packet out. The appropriate raw output 775 * routine handles any massaging necessary. 776 */ 777 s = splsoftnet(); 778 if (nam) { 779 if ((so->so_state & SS_ISCONNECTED) != 0) { 780 error = EISCONN; 781 goto die; 782 } 783 error = rip_connect_pcb(inp, (struct sockaddr_in *)nam); 784 if (error) 785 goto die; 786 } else { 787 if ((so->so_state & SS_ISCONNECTED) == 0) { 788 error = ENOTCONN; 789 goto die; 790 } 791 } 792 error = rip_output(m, inp, control, l); 793 m = NULL; 794 control = NULL; 795 if (nam) 796 rip_disconnect1(inp); 797 die: 798 if (m != NULL) 799 m_freem(m); 800 if (control != NULL) 801 m_freem(control); 802 803 splx(s); 804 return error; 805 } 806 807 static int 808 rip_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control) 809 { 810 KASSERT(solocked(so)); 811 812 m_freem(m); 813 m_freem(control); 814 815 return EOPNOTSUPP; 816 } 817 818 static int 819 rip_purgeif(struct socket *so, struct ifnet *ifp) 820 { 821 int s; 822 823 s = splsoftnet(); 824 mutex_enter(softnet_lock); 825 in_pcbpurgeif0(&rawcbtable, ifp); 826 #ifdef NET_MPSAFE 827 mutex_exit(softnet_lock); 828 #endif 829 in_purgeif(ifp); 830 #ifdef NET_MPSAFE 831 mutex_enter(softnet_lock); 832 #endif 833 in_pcbpurgeif(&rawcbtable, ifp); 834 mutex_exit(softnet_lock); 835 splx(s); 836 837 return 0; 838 } 839 840 PR_WRAP_USRREQS(rip) 841 #define rip_attach rip_attach_wrapper 842 #define rip_detach rip_detach_wrapper 843 #define rip_accept rip_accept_wrapper 844 #define rip_bind rip_bind_wrapper 845 #define rip_listen rip_listen_wrapper 846 #define rip_connect rip_connect_wrapper 847 #define rip_connect2 rip_connect2_wrapper 848 #define rip_disconnect rip_disconnect_wrapper 849 #define rip_shutdown rip_shutdown_wrapper 850 #define rip_abort rip_abort_wrapper 851 #define rip_ioctl rip_ioctl_wrapper 852 #define rip_stat rip_stat_wrapper 853 #define rip_peeraddr rip_peeraddr_wrapper 854 #define rip_sockaddr rip_sockaddr_wrapper 855 #define rip_rcvd rip_rcvd_wrapper 856 #define rip_recvoob rip_recvoob_wrapper 857 #define rip_send rip_send_wrapper 858 #define rip_sendoob rip_sendoob_wrapper 859 #define rip_purgeif rip_purgeif_wrapper 860 861 const struct pr_usrreqs rip_usrreqs = { 862 .pr_attach = rip_attach, 863 .pr_detach = rip_detach, 864 .pr_accept = rip_accept, 865 .pr_bind = rip_bind, 866 .pr_listen = rip_listen, 867 .pr_connect = rip_connect, 868 .pr_connect2 = rip_connect2, 869 .pr_disconnect = rip_disconnect, 870 .pr_shutdown = rip_shutdown, 871 .pr_abort = rip_abort, 872 .pr_ioctl = rip_ioctl, 873 .pr_stat = rip_stat, 874 .pr_peeraddr = rip_peeraddr, 875 .pr_sockaddr = rip_sockaddr, 876 .pr_rcvd = rip_rcvd, 877 .pr_recvoob = rip_recvoob, 878 .pr_send = rip_send, 879 .pr_sendoob = rip_sendoob, 880 .pr_purgeif = rip_purgeif, 881 }; 882 883 static void 884 sysctl_net_inet_raw_setup(struct sysctllog **clog) 885 { 886 887 sysctl_createv(clog, 0, NULL, NULL, 888 CTLFLAG_PERMANENT, 889 CTLTYPE_NODE, "inet", NULL, 890 NULL, 0, NULL, 0, 891 CTL_NET, PF_INET, CTL_EOL); 892 sysctl_createv(clog, 0, NULL, NULL, 893 CTLFLAG_PERMANENT, 894 CTLTYPE_NODE, "raw", 895 SYSCTL_DESCR("Raw IPv4 settings"), 896 NULL, 0, NULL, 0, 897 CTL_NET, PF_INET, IPPROTO_RAW, CTL_EOL); 898 899 sysctl_createv(clog, 0, NULL, NULL, 900 CTLFLAG_PERMANENT, 901 CTLTYPE_STRUCT, "pcblist", 902 SYSCTL_DESCR("Raw IPv4 control block list"), 903 sysctl_inpcblist, 0, &rawcbtable, 0, 904 CTL_NET, PF_INET, IPPROTO_RAW, 905 CTL_CREATE, CTL_EOL); 906 } 907