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