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