ip_sockglue.c revision 14c850212ed8f8cbb5972ad6b8812e08a0bc901c
1/* 2 * INET An implementation of the TCP/IP protocol suite for the LINUX 3 * operating system. INET is implemented using the BSD Socket 4 * interface as the means of communication with the user level. 5 * 6 * The IP to API glue. 7 * 8 * Version: $Id: ip_sockglue.c,v 1.62 2002/02/01 22:01:04 davem Exp $ 9 * 10 * Authors: see ip.c 11 * 12 * Fixes: 13 * Many : Split from ip.c , see ip.c for history. 14 * Martin Mares : TOS setting fixed. 15 * Alan Cox : Fixed a couple of oopses in Martin's 16 * TOS tweaks. 17 * Mike McLagan : Routing by source 18 */ 19 20#include <linux/config.h> 21#include <linux/module.h> 22#include <linux/types.h> 23#include <linux/mm.h> 24#include <linux/sched.h> 25#include <linux/skbuff.h> 26#include <linux/ip.h> 27#include <linux/icmp.h> 28#include <linux/inetdevice.h> 29#include <linux/netdevice.h> 30#include <net/sock.h> 31#include <net/ip.h> 32#include <net/icmp.h> 33#include <net/tcp_states.h> 34#include <linux/udp.h> 35#include <linux/igmp.h> 36#include <linux/netfilter.h> 37#include <linux/route.h> 38#include <linux/mroute.h> 39#include <net/route.h> 40#include <net/xfrm.h> 41#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 42#include <net/transp_v6.h> 43#endif 44 45#include <linux/errqueue.h> 46#include <asm/uaccess.h> 47 48#define IP_CMSG_PKTINFO 1 49#define IP_CMSG_TTL 2 50#define IP_CMSG_TOS 4 51#define IP_CMSG_RECVOPTS 8 52#define IP_CMSG_RETOPTS 16 53 54/* 55 * SOL_IP control messages. 56 */ 57 58static void ip_cmsg_recv_pktinfo(struct msghdr *msg, struct sk_buff *skb) 59{ 60 struct in_pktinfo info; 61 struct rtable *rt = (struct rtable *)skb->dst; 62 63 info.ipi_addr.s_addr = skb->nh.iph->daddr; 64 if (rt) { 65 info.ipi_ifindex = rt->rt_iif; 66 info.ipi_spec_dst.s_addr = rt->rt_spec_dst; 67 } else { 68 info.ipi_ifindex = 0; 69 info.ipi_spec_dst.s_addr = 0; 70 } 71 72 put_cmsg(msg, SOL_IP, IP_PKTINFO, sizeof(info), &info); 73} 74 75static void ip_cmsg_recv_ttl(struct msghdr *msg, struct sk_buff *skb) 76{ 77 int ttl = skb->nh.iph->ttl; 78 put_cmsg(msg, SOL_IP, IP_TTL, sizeof(int), &ttl); 79} 80 81static void ip_cmsg_recv_tos(struct msghdr *msg, struct sk_buff *skb) 82{ 83 put_cmsg(msg, SOL_IP, IP_TOS, 1, &skb->nh.iph->tos); 84} 85 86static void ip_cmsg_recv_opts(struct msghdr *msg, struct sk_buff *skb) 87{ 88 if (IPCB(skb)->opt.optlen == 0) 89 return; 90 91 put_cmsg(msg, SOL_IP, IP_RECVOPTS, IPCB(skb)->opt.optlen, skb->nh.iph+1); 92} 93 94 95static void ip_cmsg_recv_retopts(struct msghdr *msg, struct sk_buff *skb) 96{ 97 unsigned char optbuf[sizeof(struct ip_options) + 40]; 98 struct ip_options * opt = (struct ip_options*)optbuf; 99 100 if (IPCB(skb)->opt.optlen == 0) 101 return; 102 103 if (ip_options_echo(opt, skb)) { 104 msg->msg_flags |= MSG_CTRUNC; 105 return; 106 } 107 ip_options_undo(opt); 108 109 put_cmsg(msg, SOL_IP, IP_RETOPTS, opt->optlen, opt->__data); 110} 111 112 113void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb) 114{ 115 struct inet_sock *inet = inet_sk(skb->sk); 116 unsigned flags = inet->cmsg_flags; 117 118 /* Ordered by supposed usage frequency */ 119 if (flags & 1) 120 ip_cmsg_recv_pktinfo(msg, skb); 121 if ((flags>>=1) == 0) 122 return; 123 124 if (flags & 1) 125 ip_cmsg_recv_ttl(msg, skb); 126 if ((flags>>=1) == 0) 127 return; 128 129 if (flags & 1) 130 ip_cmsg_recv_tos(msg, skb); 131 if ((flags>>=1) == 0) 132 return; 133 134 if (flags & 1) 135 ip_cmsg_recv_opts(msg, skb); 136 if ((flags>>=1) == 0) 137 return; 138 139 if (flags & 1) 140 ip_cmsg_recv_retopts(msg, skb); 141} 142 143int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc) 144{ 145 int err; 146 struct cmsghdr *cmsg; 147 148 for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { 149 if (!CMSG_OK(msg, cmsg)) 150 return -EINVAL; 151 if (cmsg->cmsg_level != SOL_IP) 152 continue; 153 switch (cmsg->cmsg_type) { 154 case IP_RETOPTS: 155 err = cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)); 156 err = ip_options_get(&ipc->opt, CMSG_DATA(cmsg), err < 40 ? err : 40); 157 if (err) 158 return err; 159 break; 160 case IP_PKTINFO: 161 { 162 struct in_pktinfo *info; 163 if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct in_pktinfo))) 164 return -EINVAL; 165 info = (struct in_pktinfo *)CMSG_DATA(cmsg); 166 ipc->oif = info->ipi_ifindex; 167 ipc->addr = info->ipi_spec_dst.s_addr; 168 break; 169 } 170 default: 171 return -EINVAL; 172 } 173 } 174 return 0; 175} 176 177 178/* Special input handler for packets caught by router alert option. 179 They are selected only by protocol field, and then processed likely 180 local ones; but only if someone wants them! Otherwise, router 181 not running rsvpd will kill RSVP. 182 183 It is user level problem, what it will make with them. 184 I have no idea, how it will masquearde or NAT them (it is joke, joke :-)), 185 but receiver should be enough clever f.e. to forward mtrace requests, 186 sent to multicast group to reach destination designated router. 187 */ 188struct ip_ra_chain *ip_ra_chain; 189DEFINE_RWLOCK(ip_ra_lock); 190 191int ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct sock *)) 192{ 193 struct ip_ra_chain *ra, *new_ra, **rap; 194 195 if (sk->sk_type != SOCK_RAW || inet_sk(sk)->num == IPPROTO_RAW) 196 return -EINVAL; 197 198 new_ra = on ? kmalloc(sizeof(*new_ra), GFP_KERNEL) : NULL; 199 200 write_lock_bh(&ip_ra_lock); 201 for (rap = &ip_ra_chain; (ra=*rap) != NULL; rap = &ra->next) { 202 if (ra->sk == sk) { 203 if (on) { 204 write_unlock_bh(&ip_ra_lock); 205 kfree(new_ra); 206 return -EADDRINUSE; 207 } 208 *rap = ra->next; 209 write_unlock_bh(&ip_ra_lock); 210 211 if (ra->destructor) 212 ra->destructor(sk); 213 sock_put(sk); 214 kfree(ra); 215 return 0; 216 } 217 } 218 if (new_ra == NULL) { 219 write_unlock_bh(&ip_ra_lock); 220 return -ENOBUFS; 221 } 222 new_ra->sk = sk; 223 new_ra->destructor = destructor; 224 225 new_ra->next = ra; 226 *rap = new_ra; 227 sock_hold(sk); 228 write_unlock_bh(&ip_ra_lock); 229 230 return 0; 231} 232 233void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, 234 u16 port, u32 info, u8 *payload) 235{ 236 struct inet_sock *inet = inet_sk(sk); 237 struct sock_exterr_skb *serr; 238 239 if (!inet->recverr) 240 return; 241 242 skb = skb_clone(skb, GFP_ATOMIC); 243 if (!skb) 244 return; 245 246 serr = SKB_EXT_ERR(skb); 247 serr->ee.ee_errno = err; 248 serr->ee.ee_origin = SO_EE_ORIGIN_ICMP; 249 serr->ee.ee_type = skb->h.icmph->type; 250 serr->ee.ee_code = skb->h.icmph->code; 251 serr->ee.ee_pad = 0; 252 serr->ee.ee_info = info; 253 serr->ee.ee_data = 0; 254 serr->addr_offset = (u8*)&(((struct iphdr*)(skb->h.icmph+1))->daddr) - skb->nh.raw; 255 serr->port = port; 256 257 skb->h.raw = payload; 258 if (!skb_pull(skb, payload - skb->data) || 259 sock_queue_err_skb(sk, skb)) 260 kfree_skb(skb); 261} 262 263void ip_local_error(struct sock *sk, int err, u32 daddr, u16 port, u32 info) 264{ 265 struct inet_sock *inet = inet_sk(sk); 266 struct sock_exterr_skb *serr; 267 struct iphdr *iph; 268 struct sk_buff *skb; 269 270 if (!inet->recverr) 271 return; 272 273 skb = alloc_skb(sizeof(struct iphdr), GFP_ATOMIC); 274 if (!skb) 275 return; 276 277 iph = (struct iphdr*)skb_put(skb, sizeof(struct iphdr)); 278 skb->nh.iph = iph; 279 iph->daddr = daddr; 280 281 serr = SKB_EXT_ERR(skb); 282 serr->ee.ee_errno = err; 283 serr->ee.ee_origin = SO_EE_ORIGIN_LOCAL; 284 serr->ee.ee_type = 0; 285 serr->ee.ee_code = 0; 286 serr->ee.ee_pad = 0; 287 serr->ee.ee_info = info; 288 serr->ee.ee_data = 0; 289 serr->addr_offset = (u8*)&iph->daddr - skb->nh.raw; 290 serr->port = port; 291 292 skb->h.raw = skb->tail; 293 __skb_pull(skb, skb->tail - skb->data); 294 295 if (sock_queue_err_skb(sk, skb)) 296 kfree_skb(skb); 297} 298 299/* 300 * Handle MSG_ERRQUEUE 301 */ 302int ip_recv_error(struct sock *sk, struct msghdr *msg, int len) 303{ 304 struct sock_exterr_skb *serr; 305 struct sk_buff *skb, *skb2; 306 struct sockaddr_in *sin; 307 struct { 308 struct sock_extended_err ee; 309 struct sockaddr_in offender; 310 } errhdr; 311 int err; 312 int copied; 313 314 err = -EAGAIN; 315 skb = skb_dequeue(&sk->sk_error_queue); 316 if (skb == NULL) 317 goto out; 318 319 copied = skb->len; 320 if (copied > len) { 321 msg->msg_flags |= MSG_TRUNC; 322 copied = len; 323 } 324 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); 325 if (err) 326 goto out_free_skb; 327 328 sock_recv_timestamp(msg, sk, skb); 329 330 serr = SKB_EXT_ERR(skb); 331 332 sin = (struct sockaddr_in *)msg->msg_name; 333 if (sin) { 334 sin->sin_family = AF_INET; 335 sin->sin_addr.s_addr = *(u32*)(skb->nh.raw + serr->addr_offset); 336 sin->sin_port = serr->port; 337 memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); 338 } 339 340 memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); 341 sin = &errhdr.offender; 342 sin->sin_family = AF_UNSPEC; 343 if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP) { 344 struct inet_sock *inet = inet_sk(sk); 345 346 sin->sin_family = AF_INET; 347 sin->sin_addr.s_addr = skb->nh.iph->saddr; 348 sin->sin_port = 0; 349 memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); 350 if (inet->cmsg_flags) 351 ip_cmsg_recv(msg, skb); 352 } 353 354 put_cmsg(msg, SOL_IP, IP_RECVERR, sizeof(errhdr), &errhdr); 355 356 /* Now we could try to dump offended packet options */ 357 358 msg->msg_flags |= MSG_ERRQUEUE; 359 err = copied; 360 361 /* Reset and regenerate socket error */ 362 spin_lock_bh(&sk->sk_error_queue.lock); 363 sk->sk_err = 0; 364 if ((skb2 = skb_peek(&sk->sk_error_queue)) != NULL) { 365 sk->sk_err = SKB_EXT_ERR(skb2)->ee.ee_errno; 366 spin_unlock_bh(&sk->sk_error_queue.lock); 367 sk->sk_error_report(sk); 368 } else 369 spin_unlock_bh(&sk->sk_error_queue.lock); 370 371out_free_skb: 372 kfree_skb(skb); 373out: 374 return err; 375} 376 377 378/* 379 * Socket option code for IP. This is the end of the line after any TCP,UDP etc options on 380 * an IP socket. 381 */ 382 383int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen) 384{ 385 struct inet_sock *inet = inet_sk(sk); 386 int val=0,err; 387 388 if (level != SOL_IP) 389 return -ENOPROTOOPT; 390 391 if (((1<<optname) & ((1<<IP_PKTINFO) | (1<<IP_RECVTTL) | 392 (1<<IP_RECVOPTS) | (1<<IP_RECVTOS) | 393 (1<<IP_RETOPTS) | (1<<IP_TOS) | 394 (1<<IP_TTL) | (1<<IP_HDRINCL) | 395 (1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) | 396 (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND))) || 397 optname == IP_MULTICAST_TTL || 398 optname == IP_MULTICAST_LOOP) { 399 if (optlen >= sizeof(int)) { 400 if (get_user(val, (int __user *) optval)) 401 return -EFAULT; 402 } else if (optlen >= sizeof(char)) { 403 unsigned char ucval; 404 405 if (get_user(ucval, (unsigned char __user *) optval)) 406 return -EFAULT; 407 val = (int) ucval; 408 } 409 } 410 411 /* If optlen==0, it is equivalent to val == 0 */ 412 413#ifdef CONFIG_IP_MROUTE 414 if (optname >= MRT_BASE && optname <= (MRT_BASE + 10)) 415 return ip_mroute_setsockopt(sk,optname,optval,optlen); 416#endif 417 418 err = 0; 419 lock_sock(sk); 420 421 switch (optname) { 422 case IP_OPTIONS: 423 { 424 struct ip_options * opt = NULL; 425 if (optlen > 40 || optlen < 0) 426 goto e_inval; 427 err = ip_options_get_from_user(&opt, optval, optlen); 428 if (err) 429 break; 430 if (inet->is_icsk) { 431 struct inet_connection_sock *icsk = inet_csk(sk); 432#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 433 if (sk->sk_family == PF_INET || 434 (!((1 << sk->sk_state) & 435 (TCPF_LISTEN | TCPF_CLOSE)) && 436 inet->daddr != LOOPBACK4_IPV6)) { 437#endif 438 if (inet->opt) 439 icsk->icsk_ext_hdr_len -= inet->opt->optlen; 440 if (opt) 441 icsk->icsk_ext_hdr_len += opt->optlen; 442 icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); 443#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 444 } 445#endif 446 } 447 opt = xchg(&inet->opt, opt); 448 kfree(opt); 449 break; 450 } 451 case IP_PKTINFO: 452 if (val) 453 inet->cmsg_flags |= IP_CMSG_PKTINFO; 454 else 455 inet->cmsg_flags &= ~IP_CMSG_PKTINFO; 456 break; 457 case IP_RECVTTL: 458 if (val) 459 inet->cmsg_flags |= IP_CMSG_TTL; 460 else 461 inet->cmsg_flags &= ~IP_CMSG_TTL; 462 break; 463 case IP_RECVTOS: 464 if (val) 465 inet->cmsg_flags |= IP_CMSG_TOS; 466 else 467 inet->cmsg_flags &= ~IP_CMSG_TOS; 468 break; 469 case IP_RECVOPTS: 470 if (val) 471 inet->cmsg_flags |= IP_CMSG_RECVOPTS; 472 else 473 inet->cmsg_flags &= ~IP_CMSG_RECVOPTS; 474 break; 475 case IP_RETOPTS: 476 if (val) 477 inet->cmsg_flags |= IP_CMSG_RETOPTS; 478 else 479 inet->cmsg_flags &= ~IP_CMSG_RETOPTS; 480 break; 481 case IP_TOS: /* This sets both TOS and Precedence */ 482 if (sk->sk_type == SOCK_STREAM) { 483 val &= ~3; 484 val |= inet->tos & 3; 485 } 486 if (IPTOS_PREC(val) >= IPTOS_PREC_CRITIC_ECP && 487 !capable(CAP_NET_ADMIN)) { 488 err = -EPERM; 489 break; 490 } 491 if (inet->tos != val) { 492 inet->tos = val; 493 sk->sk_priority = rt_tos2priority(val); 494 sk_dst_reset(sk); 495 } 496 break; 497 case IP_TTL: 498 if (optlen<1) 499 goto e_inval; 500 if (val != -1 && (val < 1 || val>255)) 501 goto e_inval; 502 inet->uc_ttl = val; 503 break; 504 case IP_HDRINCL: 505 if (sk->sk_type != SOCK_RAW) { 506 err = -ENOPROTOOPT; 507 break; 508 } 509 inet->hdrincl = val ? 1 : 0; 510 break; 511 case IP_MTU_DISCOVER: 512 if (val<0 || val>2) 513 goto e_inval; 514 inet->pmtudisc = val; 515 break; 516 case IP_RECVERR: 517 inet->recverr = !!val; 518 if (!val) 519 skb_queue_purge(&sk->sk_error_queue); 520 break; 521 case IP_MULTICAST_TTL: 522 if (sk->sk_type == SOCK_STREAM) 523 goto e_inval; 524 if (optlen<1) 525 goto e_inval; 526 if (val==-1) 527 val = 1; 528 if (val < 0 || val > 255) 529 goto e_inval; 530 inet->mc_ttl = val; 531 break; 532 case IP_MULTICAST_LOOP: 533 if (optlen<1) 534 goto e_inval; 535 inet->mc_loop = !!val; 536 break; 537 case IP_MULTICAST_IF: 538 { 539 struct ip_mreqn mreq; 540 struct net_device *dev = NULL; 541 542 if (sk->sk_type == SOCK_STREAM) 543 goto e_inval; 544 /* 545 * Check the arguments are allowable 546 */ 547 548 err = -EFAULT; 549 if (optlen >= sizeof(struct ip_mreqn)) { 550 if (copy_from_user(&mreq,optval,sizeof(mreq))) 551 break; 552 } else { 553 memset(&mreq, 0, sizeof(mreq)); 554 if (optlen >= sizeof(struct in_addr) && 555 copy_from_user(&mreq.imr_address,optval,sizeof(struct in_addr))) 556 break; 557 } 558 559 if (!mreq.imr_ifindex) { 560 if (mreq.imr_address.s_addr == INADDR_ANY) { 561 inet->mc_index = 0; 562 inet->mc_addr = 0; 563 err = 0; 564 break; 565 } 566 dev = ip_dev_find(mreq.imr_address.s_addr); 567 if (dev) { 568 mreq.imr_ifindex = dev->ifindex; 569 dev_put(dev); 570 } 571 } else 572 dev = __dev_get_by_index(mreq.imr_ifindex); 573 574 575 err = -EADDRNOTAVAIL; 576 if (!dev) 577 break; 578 579 err = -EINVAL; 580 if (sk->sk_bound_dev_if && 581 mreq.imr_ifindex != sk->sk_bound_dev_if) 582 break; 583 584 inet->mc_index = mreq.imr_ifindex; 585 inet->mc_addr = mreq.imr_address.s_addr; 586 err = 0; 587 break; 588 } 589 590 case IP_ADD_MEMBERSHIP: 591 case IP_DROP_MEMBERSHIP: 592 { 593 struct ip_mreqn mreq; 594 595 if (optlen < sizeof(struct ip_mreq)) 596 goto e_inval; 597 err = -EFAULT; 598 if (optlen >= sizeof(struct ip_mreqn)) { 599 if(copy_from_user(&mreq,optval,sizeof(mreq))) 600 break; 601 } else { 602 memset(&mreq, 0, sizeof(mreq)); 603 if (copy_from_user(&mreq,optval,sizeof(struct ip_mreq))) 604 break; 605 } 606 607 if (optname == IP_ADD_MEMBERSHIP) 608 err = ip_mc_join_group(sk, &mreq); 609 else 610 err = ip_mc_leave_group(sk, &mreq); 611 break; 612 } 613 case IP_MSFILTER: 614 { 615 extern int sysctl_igmp_max_msf; 616 struct ip_msfilter *msf; 617 618 if (optlen < IP_MSFILTER_SIZE(0)) 619 goto e_inval; 620 if (optlen > sysctl_optmem_max) { 621 err = -ENOBUFS; 622 break; 623 } 624 msf = (struct ip_msfilter *)kmalloc(optlen, GFP_KERNEL); 625 if (msf == 0) { 626 err = -ENOBUFS; 627 break; 628 } 629 err = -EFAULT; 630 if (copy_from_user(msf, optval, optlen)) { 631 kfree(msf); 632 break; 633 } 634 /* numsrc >= (1G-4) overflow in 32 bits */ 635 if (msf->imsf_numsrc >= 0x3ffffffcU || 636 msf->imsf_numsrc > sysctl_igmp_max_msf) { 637 kfree(msf); 638 err = -ENOBUFS; 639 break; 640 } 641 if (IP_MSFILTER_SIZE(msf->imsf_numsrc) > optlen) { 642 kfree(msf); 643 err = -EINVAL; 644 break; 645 } 646 err = ip_mc_msfilter(sk, msf, 0); 647 kfree(msf); 648 break; 649 } 650 case IP_BLOCK_SOURCE: 651 case IP_UNBLOCK_SOURCE: 652 case IP_ADD_SOURCE_MEMBERSHIP: 653 case IP_DROP_SOURCE_MEMBERSHIP: 654 { 655 struct ip_mreq_source mreqs; 656 int omode, add; 657 658 if (optlen != sizeof(struct ip_mreq_source)) 659 goto e_inval; 660 if (copy_from_user(&mreqs, optval, sizeof(mreqs))) { 661 err = -EFAULT; 662 break; 663 } 664 if (optname == IP_BLOCK_SOURCE) { 665 omode = MCAST_EXCLUDE; 666 add = 1; 667 } else if (optname == IP_UNBLOCK_SOURCE) { 668 omode = MCAST_EXCLUDE; 669 add = 0; 670 } else if (optname == IP_ADD_SOURCE_MEMBERSHIP) { 671 struct ip_mreqn mreq; 672 673 mreq.imr_multiaddr.s_addr = mreqs.imr_multiaddr; 674 mreq.imr_address.s_addr = mreqs.imr_interface; 675 mreq.imr_ifindex = 0; 676 err = ip_mc_join_group(sk, &mreq); 677 if (err && err != -EADDRINUSE) 678 break; 679 omode = MCAST_INCLUDE; 680 add = 1; 681 } else /* IP_DROP_SOURCE_MEMBERSHIP */ { 682 omode = MCAST_INCLUDE; 683 add = 0; 684 } 685 err = ip_mc_source(add, omode, sk, &mreqs, 0); 686 break; 687 } 688 case MCAST_JOIN_GROUP: 689 case MCAST_LEAVE_GROUP: 690 { 691 struct group_req greq; 692 struct sockaddr_in *psin; 693 struct ip_mreqn mreq; 694 695 if (optlen < sizeof(struct group_req)) 696 goto e_inval; 697 err = -EFAULT; 698 if(copy_from_user(&greq, optval, sizeof(greq))) 699 break; 700 psin = (struct sockaddr_in *)&greq.gr_group; 701 if (psin->sin_family != AF_INET) 702 goto e_inval; 703 memset(&mreq, 0, sizeof(mreq)); 704 mreq.imr_multiaddr = psin->sin_addr; 705 mreq.imr_ifindex = greq.gr_interface; 706 707 if (optname == MCAST_JOIN_GROUP) 708 err = ip_mc_join_group(sk, &mreq); 709 else 710 err = ip_mc_leave_group(sk, &mreq); 711 break; 712 } 713 case MCAST_JOIN_SOURCE_GROUP: 714 case MCAST_LEAVE_SOURCE_GROUP: 715 case MCAST_BLOCK_SOURCE: 716 case MCAST_UNBLOCK_SOURCE: 717 { 718 struct group_source_req greqs; 719 struct ip_mreq_source mreqs; 720 struct sockaddr_in *psin; 721 int omode, add; 722 723 if (optlen != sizeof(struct group_source_req)) 724 goto e_inval; 725 if (copy_from_user(&greqs, optval, sizeof(greqs))) { 726 err = -EFAULT; 727 break; 728 } 729 if (greqs.gsr_group.ss_family != AF_INET || 730 greqs.gsr_source.ss_family != AF_INET) { 731 err = -EADDRNOTAVAIL; 732 break; 733 } 734 psin = (struct sockaddr_in *)&greqs.gsr_group; 735 mreqs.imr_multiaddr = psin->sin_addr.s_addr; 736 psin = (struct sockaddr_in *)&greqs.gsr_source; 737 mreqs.imr_sourceaddr = psin->sin_addr.s_addr; 738 mreqs.imr_interface = 0; /* use index for mc_source */ 739 740 if (optname == MCAST_BLOCK_SOURCE) { 741 omode = MCAST_EXCLUDE; 742 add = 1; 743 } else if (optname == MCAST_UNBLOCK_SOURCE) { 744 omode = MCAST_EXCLUDE; 745 add = 0; 746 } else if (optname == MCAST_JOIN_SOURCE_GROUP) { 747 struct ip_mreqn mreq; 748 749 psin = (struct sockaddr_in *)&greqs.gsr_group; 750 mreq.imr_multiaddr = psin->sin_addr; 751 mreq.imr_address.s_addr = 0; 752 mreq.imr_ifindex = greqs.gsr_interface; 753 err = ip_mc_join_group(sk, &mreq); 754 if (err && err != -EADDRINUSE) 755 break; 756 greqs.gsr_interface = mreq.imr_ifindex; 757 omode = MCAST_INCLUDE; 758 add = 1; 759 } else /* MCAST_LEAVE_SOURCE_GROUP */ { 760 omode = MCAST_INCLUDE; 761 add = 0; 762 } 763 err = ip_mc_source(add, omode, sk, &mreqs, 764 greqs.gsr_interface); 765 break; 766 } 767 case MCAST_MSFILTER: 768 { 769 extern int sysctl_igmp_max_msf; 770 struct sockaddr_in *psin; 771 struct ip_msfilter *msf = NULL; 772 struct group_filter *gsf = NULL; 773 int msize, i, ifindex; 774 775 if (optlen < GROUP_FILTER_SIZE(0)) 776 goto e_inval; 777 if (optlen > sysctl_optmem_max) { 778 err = -ENOBUFS; 779 break; 780 } 781 gsf = (struct group_filter *)kmalloc(optlen,GFP_KERNEL); 782 if (gsf == 0) { 783 err = -ENOBUFS; 784 break; 785 } 786 err = -EFAULT; 787 if (copy_from_user(gsf, optval, optlen)) { 788 goto mc_msf_out; 789 } 790 /* numsrc >= (4G-140)/128 overflow in 32 bits */ 791 if (gsf->gf_numsrc >= 0x1ffffff || 792 gsf->gf_numsrc > sysctl_igmp_max_msf) { 793 err = -ENOBUFS; 794 goto mc_msf_out; 795 } 796 if (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) { 797 err = -EINVAL; 798 goto mc_msf_out; 799 } 800 msize = IP_MSFILTER_SIZE(gsf->gf_numsrc); 801 msf = (struct ip_msfilter *)kmalloc(msize,GFP_KERNEL); 802 if (msf == 0) { 803 err = -ENOBUFS; 804 goto mc_msf_out; 805 } 806 ifindex = gsf->gf_interface; 807 psin = (struct sockaddr_in *)&gsf->gf_group; 808 if (psin->sin_family != AF_INET) { 809 err = -EADDRNOTAVAIL; 810 goto mc_msf_out; 811 } 812 msf->imsf_multiaddr = psin->sin_addr.s_addr; 813 msf->imsf_interface = 0; 814 msf->imsf_fmode = gsf->gf_fmode; 815 msf->imsf_numsrc = gsf->gf_numsrc; 816 err = -EADDRNOTAVAIL; 817 for (i=0; i<gsf->gf_numsrc; ++i) { 818 psin = (struct sockaddr_in *)&gsf->gf_slist[i]; 819 820 if (psin->sin_family != AF_INET) 821 goto mc_msf_out; 822 msf->imsf_slist[i] = psin->sin_addr.s_addr; 823 } 824 kfree(gsf); 825 gsf = NULL; 826 827 err = ip_mc_msfilter(sk, msf, ifindex); 828mc_msf_out: 829 kfree(msf); 830 kfree(gsf); 831 break; 832 } 833 case IP_ROUTER_ALERT: 834 err = ip_ra_control(sk, val ? 1 : 0, NULL); 835 break; 836 837 case IP_FREEBIND: 838 if (optlen<1) 839 goto e_inval; 840 inet->freebind = !!val; 841 break; 842 843 case IP_IPSEC_POLICY: 844 case IP_XFRM_POLICY: 845 err = -EPERM; 846 if (!capable(CAP_NET_ADMIN)) 847 break; 848 err = xfrm_user_policy(sk, optname, optval, optlen); 849 break; 850 851 default: 852#ifdef CONFIG_NETFILTER 853 err = nf_setsockopt(sk, PF_INET, optname, optval, 854 optlen); 855#else 856 err = -ENOPROTOOPT; 857#endif 858 break; 859 } 860 release_sock(sk); 861 return err; 862 863e_inval: 864 release_sock(sk); 865 return -EINVAL; 866} 867 868/* 869 * Get the options. Note for future reference. The GET of IP options gets the 870 * _received_ ones. The set sets the _sent_ ones. 871 */ 872 873int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) 874{ 875 struct inet_sock *inet = inet_sk(sk); 876 int val; 877 int len; 878 879 if(level!=SOL_IP) 880 return -EOPNOTSUPP; 881 882#ifdef CONFIG_IP_MROUTE 883 if(optname>=MRT_BASE && optname <=MRT_BASE+10) 884 { 885 return ip_mroute_getsockopt(sk,optname,optval,optlen); 886 } 887#endif 888 889 if(get_user(len,optlen)) 890 return -EFAULT; 891 if(len < 0) 892 return -EINVAL; 893 894 lock_sock(sk); 895 896 switch(optname) { 897 case IP_OPTIONS: 898 { 899 unsigned char optbuf[sizeof(struct ip_options)+40]; 900 struct ip_options * opt = (struct ip_options*)optbuf; 901 opt->optlen = 0; 902 if (inet->opt) 903 memcpy(optbuf, inet->opt, 904 sizeof(struct ip_options)+ 905 inet->opt->optlen); 906 release_sock(sk); 907 908 if (opt->optlen == 0) 909 return put_user(0, optlen); 910 911 ip_options_undo(opt); 912 913 len = min_t(unsigned int, len, opt->optlen); 914 if(put_user(len, optlen)) 915 return -EFAULT; 916 if(copy_to_user(optval, opt->__data, len)) 917 return -EFAULT; 918 return 0; 919 } 920 case IP_PKTINFO: 921 val = (inet->cmsg_flags & IP_CMSG_PKTINFO) != 0; 922 break; 923 case IP_RECVTTL: 924 val = (inet->cmsg_flags & IP_CMSG_TTL) != 0; 925 break; 926 case IP_RECVTOS: 927 val = (inet->cmsg_flags & IP_CMSG_TOS) != 0; 928 break; 929 case IP_RECVOPTS: 930 val = (inet->cmsg_flags & IP_CMSG_RECVOPTS) != 0; 931 break; 932 case IP_RETOPTS: 933 val = (inet->cmsg_flags & IP_CMSG_RETOPTS) != 0; 934 break; 935 case IP_TOS: 936 val = inet->tos; 937 break; 938 case IP_TTL: 939 val = (inet->uc_ttl == -1 ? 940 sysctl_ip_default_ttl : 941 inet->uc_ttl); 942 break; 943 case IP_HDRINCL: 944 val = inet->hdrincl; 945 break; 946 case IP_MTU_DISCOVER: 947 val = inet->pmtudisc; 948 break; 949 case IP_MTU: 950 { 951 struct dst_entry *dst; 952 val = 0; 953 dst = sk_dst_get(sk); 954 if (dst) { 955 val = dst_mtu(dst); 956 dst_release(dst); 957 } 958 if (!val) { 959 release_sock(sk); 960 return -ENOTCONN; 961 } 962 break; 963 } 964 case IP_RECVERR: 965 val = inet->recverr; 966 break; 967 case IP_MULTICAST_TTL: 968 val = inet->mc_ttl; 969 break; 970 case IP_MULTICAST_LOOP: 971 val = inet->mc_loop; 972 break; 973 case IP_MULTICAST_IF: 974 { 975 struct in_addr addr; 976 len = min_t(unsigned int, len, sizeof(struct in_addr)); 977 addr.s_addr = inet->mc_addr; 978 release_sock(sk); 979 980 if(put_user(len, optlen)) 981 return -EFAULT; 982 if(copy_to_user(optval, &addr, len)) 983 return -EFAULT; 984 return 0; 985 } 986 case IP_MSFILTER: 987 { 988 struct ip_msfilter msf; 989 int err; 990 991 if (len < IP_MSFILTER_SIZE(0)) { 992 release_sock(sk); 993 return -EINVAL; 994 } 995 if (copy_from_user(&msf, optval, IP_MSFILTER_SIZE(0))) { 996 release_sock(sk); 997 return -EFAULT; 998 } 999 err = ip_mc_msfget(sk, &msf, 1000 (struct ip_msfilter __user *)optval, optlen); 1001 release_sock(sk); 1002 return err; 1003 } 1004 case MCAST_MSFILTER: 1005 { 1006 struct group_filter gsf; 1007 int err; 1008 1009 if (len < GROUP_FILTER_SIZE(0)) { 1010 release_sock(sk); 1011 return -EINVAL; 1012 } 1013 if (copy_from_user(&gsf, optval, GROUP_FILTER_SIZE(0))) { 1014 release_sock(sk); 1015 return -EFAULT; 1016 } 1017 err = ip_mc_gsfget(sk, &gsf, 1018 (struct group_filter __user *)optval, optlen); 1019 release_sock(sk); 1020 return err; 1021 } 1022 case IP_PKTOPTIONS: 1023 { 1024 struct msghdr msg; 1025 1026 release_sock(sk); 1027 1028 if (sk->sk_type != SOCK_STREAM) 1029 return -ENOPROTOOPT; 1030 1031 msg.msg_control = optval; 1032 msg.msg_controllen = len; 1033 msg.msg_flags = 0; 1034 1035 if (inet->cmsg_flags & IP_CMSG_PKTINFO) { 1036 struct in_pktinfo info; 1037 1038 info.ipi_addr.s_addr = inet->rcv_saddr; 1039 info.ipi_spec_dst.s_addr = inet->rcv_saddr; 1040 info.ipi_ifindex = inet->mc_index; 1041 put_cmsg(&msg, SOL_IP, IP_PKTINFO, sizeof(info), &info); 1042 } 1043 if (inet->cmsg_flags & IP_CMSG_TTL) { 1044 int hlim = inet->mc_ttl; 1045 put_cmsg(&msg, SOL_IP, IP_TTL, sizeof(hlim), &hlim); 1046 } 1047 len -= msg.msg_controllen; 1048 return put_user(len, optlen); 1049 } 1050 case IP_FREEBIND: 1051 val = inet->freebind; 1052 break; 1053 default: 1054#ifdef CONFIG_NETFILTER 1055 val = nf_getsockopt(sk, PF_INET, optname, optval, 1056 &len); 1057 release_sock(sk); 1058 if (val >= 0) 1059 val = put_user(len, optlen); 1060 return val; 1061#else 1062 release_sock(sk); 1063 return -ENOPROTOOPT; 1064#endif 1065 } 1066 release_sock(sk); 1067 1068 if (len < sizeof(int) && len > 0 && val>=0 && val<255) { 1069 unsigned char ucval = (unsigned char)val; 1070 len = 1; 1071 if(put_user(len, optlen)) 1072 return -EFAULT; 1073 if(copy_to_user(optval,&ucval,1)) 1074 return -EFAULT; 1075 } else { 1076 len = min_t(unsigned int, sizeof(int), len); 1077 if(put_user(len, optlen)) 1078 return -EFAULT; 1079 if(copy_to_user(optval,&val,len)) 1080 return -EFAULT; 1081 } 1082 return 0; 1083} 1084 1085EXPORT_SYMBOL(ip_cmsg_recv); 1086 1087EXPORT_SYMBOL(ip_getsockopt); 1088EXPORT_SYMBOL(ip_setsockopt); 1089