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