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