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