00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
#include <linux/config.h>
00021
#include <linux/types.h>
00022
#include <linux/mm.h>
00023
#include <linux/sched.h>
00024
#include <linux/skbuff.h>
00025
#include <linux/ip.h>
00026
#include <linux/icmp.h>
00027
#include <linux/netdevice.h>
00028
#include <net/sock.h>
00029
#include <net/ip.h>
00030
#include <net/icmp.h>
00031
#include <net/tcp.h>
00032
#include <linux/tcp.h>
00033
#include <linux/udp.h>
00034
#include <linux/igmp.h>
00035
#include <linux/netfilter.h>
00036
#include <linux/route.h>
00037
#include <linux/mroute.h>
00038
#include <net/route.h>
00039
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
00040
#include <net/transp_v6.h>
00041
#endif
00042
00043
#include <linux/errqueue.h>
00044
#include <asm/uaccess.h>
00045
00046 #define IP_CMSG_PKTINFO 1
00047 #define IP_CMSG_TTL 2
00048 #define IP_CMSG_TOS 4
00049 #define IP_CMSG_RECVOPTS 8
00050 #define IP_CMSG_RETOPTS 16
00051
00052
00053
00054
00055
00056 static void ip_cmsg_recv_pktinfo(
struct msghdr *msg,
struct sk_buff *skb)
00057 {
00058
struct in_pktinfo info;
00059
struct rtable *rt = (
struct rtable *)skb->
dst;
00060
00061 info.
ipi_addr.
s_addr = skb->
nh.iph->daddr;
00062
if (rt) {
00063 info.
ipi_ifindex = rt->rt_iif;
00064 info.
ipi_spec_dst.
s_addr = rt->rt_spec_dst;
00065 }
else {
00066 info.
ipi_ifindex = 0;
00067 info.
ipi_spec_dst.
s_addr = 0;
00068 }
00069
00070
put_cmsg(msg, SOL_IP,
IP_PKTINFO,
sizeof(info), &info);
00071 }
00072
00073 static void ip_cmsg_recv_ttl(
struct msghdr *msg,
struct sk_buff *skb)
00074 {
00075
int ttl = skb->
nh.iph->ttl;
00076
put_cmsg(msg, SOL_IP,
IP_TTL,
sizeof(
int), &ttl);
00077 }
00078
00079 static void ip_cmsg_recv_tos(
struct msghdr *msg,
struct sk_buff *skb)
00080 {
00081
put_cmsg(msg, SOL_IP,
IP_TOS, 1, &skb->
nh.iph->tos);
00082 }
00083
00084 static void ip_cmsg_recv_opts(
struct msghdr *msg,
struct sk_buff *skb)
00085 {
00086
if (
IPCB(skb)->opt.optlen == 0)
00087
return;
00088
00089
put_cmsg(msg, SOL_IP,
IP_RECVOPTS,
IPCB(skb)->opt.optlen, skb->
nh.iph+1);
00090 }
00091
00092
00093 void ip_cmsg_recv_retopts(
struct msghdr *msg,
struct sk_buff *skb)
00094 {
00095
unsigned char optbuf[
sizeof(
struct ip_options) + 40];
00096
struct ip_options * opt = (
struct ip_options*)optbuf;
00097
00098
if (
IPCB(skb)->opt.optlen == 0)
00099
return;
00100
00101
if (
ip_options_echo(opt, skb)) {
00102 msg->msg_flags |= MSG_CTRUNC;
00103
return;
00104 }
00105
ip_options_undo(opt);
00106
00107
put_cmsg(msg, SOL_IP,
IP_RETOPTS, opt->optlen, opt->__data);
00108 }
00109
00110
00111 void ip_cmsg_recv(
struct msghdr *msg,
struct sk_buff *skb)
00112 {
00113
unsigned flags = skb->
sk->
protinfo.af_inet.cmsg_flags;
00114
00115
00116
if (flags & 1)
00117
ip_cmsg_recv_pktinfo(msg, skb);
00118
if ((flags>>=1) == 0)
00119
return;
00120
00121
if (flags & 1)
00122
ip_cmsg_recv_ttl(msg, skb);
00123
if ((flags>>=1) == 0)
00124
return;
00125
00126
if (flags & 1)
00127
ip_cmsg_recv_tos(msg, skb);
00128
if ((flags>>=1) == 0)
00129
return;
00130
00131
if (flags & 1)
00132
ip_cmsg_recv_opts(msg, skb);
00133
if ((flags>>=1) == 0)
00134
return;
00135
00136
if (flags & 1)
00137
ip_cmsg_recv_retopts(msg, skb);
00138 }
00139
00140 int ip_cmsg_send(
struct msghdr *msg,
struct ipcm_cookie *ipc)
00141 {
00142
int err;
00143
struct cmsghdr *cmsg;
00144
00145
for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
00146
if (cmsg->cmsg_len <
sizeof(
struct cmsghdr) ||
00147 (unsigned long)(((char*)cmsg - (
char*)msg->msg_control)
00148 + cmsg->cmsg_len) > msg->msg_controllen) {
00149
return -EINVAL;
00150 }
00151
if (cmsg->cmsg_level != SOL_IP)
00152
continue;
00153
switch (cmsg->cmsg_type) {
00154
case IP_RETOPTS:
00155 err = cmsg->cmsg_len - CMSG_ALIGN(
sizeof(
struct cmsghdr));
00156 err =
ip_options_get(&ipc->
opt, CMSG_DATA(cmsg), err < 40 ? err : 40, 0);
00157
if (err)
00158
return err;
00159
break;
00160
case IP_PKTINFO:
00161 {
00162
struct in_pktinfo *info;
00163
if (cmsg->cmsg_len != CMSG_LEN(
sizeof(
struct in_pktinfo)))
00164
return -EINVAL;
00165 info = (
struct in_pktinfo *)CMSG_DATA(cmsg);
00166 ipc->
oif = info->ipi_ifindex;
00167 ipc->
addr = info->ipi_spec_dst.s_addr;
00168
break;
00169 }
00170
default:
00171
return -EINVAL;
00172 }
00173 }
00174
return 0;
00175 }
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 struct ip_ra_chain *
ip_ra_chain;
00189 rwlock_t
ip_ra_lock = RW_LOCK_UNLOCKED;
00190
00191 int ip_ra_control(
struct sock *sk,
unsigned char on,
void (*destructor)(
struct sock *))
00192 {
00193
struct ip_ra_chain *ra, *new_ra, **rap;
00194
00195
if (sk->
type != SOCK_RAW || sk->
num ==
IPPROTO_RAW)
00196
return -EINVAL;
00197
00198 new_ra = on ? kmalloc(
sizeof(*new_ra), GFP_KERNEL) : NULL;
00199
00200 write_lock_bh(&
ip_ra_lock);
00201
for (rap = &
ip_ra_chain; (ra=*rap) != NULL; rap = &ra->next) {
00202
if (ra->sk == sk) {
00203
if (on) {
00204 write_unlock_bh(&
ip_ra_lock);
00205
if (new_ra)
00206 kfree(new_ra);
00207
return -EADDRINUSE;
00208 }
00209 *rap = ra->next;
00210 write_unlock_bh(&
ip_ra_lock);
00211
00212
if (ra->destructor)
00213 ra->destructor(sk);
00214
sock_put(sk);
00215 kfree(ra);
00216
return 0;
00217 }
00218 }
00219
if (new_ra == NULL) {
00220 write_unlock_bh(&
ip_ra_lock);
00221
return -ENOBUFS;
00222 }
00223 new_ra->sk = sk;
00224 new_ra->destructor = destructor;
00225
00226 new_ra->
next = ra;
00227 *rap = new_ra;
00228
sock_hold(sk);
00229 write_unlock_bh(&
ip_ra_lock);
00230
00231
return 0;
00232 }
00233
00234 void ip_icmp_error(
struct sock *sk,
struct sk_buff *skb,
int err,
00235 u16 port, u32 info, u8 *payload)
00236 {
00237
struct sock_exterr_skb *serr;
00238
00239
if (!sk->
protinfo.af_inet.recverr)
00240
return;
00241
00242 skb =
skb_clone(skb, GFP_ATOMIC);
00243
if (!skb)
00244
return;
00245
00246 serr = SKB_EXT_ERR(skb);
00247 serr->ee.ee_errno = err;
00248 serr->ee.ee_origin = SO_EE_ORIGIN_ICMP;
00249 serr->ee.ee_type = skb->
h.icmph->type;
00250 serr->ee.ee_code = skb->
h.icmph->code;
00251 serr->ee.ee_pad = 0;
00252 serr->ee.ee_info = info;
00253 serr->ee.ee_data = 0;
00254 serr->addr_offset = (u8*)&(((
struct iphdr*)(skb->
h.icmph+1))->daddr) - skb->
nh.raw;
00255 serr->port = port;
00256
00257 skb->
h.raw = payload;
00258
if (!
skb_pull(skb, payload - skb->
data) ||
00259
sock_queue_err_skb(sk, skb))
00260
kfree_skb(skb);
00261 }
00262
00263 void ip_local_error(
struct sock *sk,
int err, u32 daddr, u16 port, u32 info)
00264 {
00265
struct sock_exterr_skb *serr;
00266
struct iphdr *iph;
00267
struct sk_buff *skb;
00268
00269
if (!sk->
protinfo.af_inet.recverr)
00270
return;
00271
00272 skb =
alloc_skb(
sizeof(
struct iphdr), GFP_ATOMIC);
00273
if (!skb)
00274
return;
00275
00276 iph = (
struct iphdr*)
skb_put(skb,
sizeof(
struct iphdr));
00277 skb->nh.iph = iph;
00278 iph->daddr = daddr;
00279
00280 serr = SKB_EXT_ERR(skb);
00281 serr->ee.ee_errno = err;
00282 serr->ee.ee_origin = SO_EE_ORIGIN_LOCAL;
00283 serr->ee.ee_type = 0;
00284 serr->ee.ee_code = 0;
00285 serr->ee.ee_pad = 0;
00286 serr->ee.ee_info = info;
00287 serr->ee.ee_data = 0;
00288 serr->addr_offset = (u8*)&iph->daddr - skb->nh.raw;
00289 serr->port = port;
00290
00291 skb->h.raw = skb->tail;
00292
__skb_pull(skb, skb->tail - skb->data);
00293
00294
if (
sock_queue_err_skb(sk, skb))
00295
kfree_skb(skb);
00296 }
00297
00298
00299
00300
00301 int ip_recv_error(
struct sock *sk,
struct msghdr *msg,
int len)
00302 {
00303
struct sock_exterr_skb *serr;
00304
struct sk_buff *skb, *skb2;
00305
struct sockaddr_in *sin;
00306
struct {
00307
struct sock_extended_err ee;
00308
struct sockaddr_in offender;
00309 } errhdr;
00310
int err;
00311
int copied;
00312
00313 err = -EAGAIN;
00314 skb =
skb_dequeue(&sk->
error_queue);
00315
if (skb == NULL)
00316
goto out;
00317
00318 copied = skb->len;
00319
if (copied > len) {
00320 msg->msg_flags |= MSG_TRUNC;
00321 copied = len;
00322 }
00323 err =
skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
00324
if (err)
00325
goto out_free_skb;
00326
00327
sock_recv_timestamp(msg, sk, skb);
00328
00329 serr = SKB_EXT_ERR(skb);
00330
00331 sin = (
struct sockaddr_in *)msg->msg_name;
00332
if (sin) {
00333 sin->sin_family = AF_INET;
00334 sin->sin_addr.s_addr = *(u32*)(skb->nh.raw + serr->addr_offset);
00335 sin->sin_port = serr->port;
00336 memset(&sin->sin_zero, 0,
sizeof(sin->sin_zero));
00337 }
00338
00339 memcpy(&errhdr.ee, &serr->ee,
sizeof(
struct sock_extended_err));
00340 sin = &errhdr.offender;
00341 sin->sin_family = AF_UNSPEC;
00342
if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP) {
00343 sin->sin_family = AF_INET;
00344 sin->sin_addr.s_addr = skb->nh.iph->saddr;
00345 sin->sin_port = 0;
00346 memset(&sin->sin_zero, 0,
sizeof(sin->sin_zero));
00347
if (sk->
protinfo.af_inet.cmsg_flags)
00348
ip_cmsg_recv(msg, skb);
00349 }
00350
00351
put_cmsg(msg, SOL_IP,
IP_RECVERR,
sizeof(errhdr), &errhdr);
00352
00353
00354
00355 msg->msg_flags |= MSG_ERRQUEUE;
00356 err = copied;
00357
00358
00359 spin_lock_irq(&sk->
error_queue.
lock);
00360 sk->
err = 0;
00361
if ((skb2 =
skb_peek(&sk->
error_queue)) != NULL) {
00362 sk->
err = SKB_EXT_ERR(skb2)->ee.ee_errno;
00363 spin_unlock_irq(&sk->
error_queue.
lock);
00364 sk->
error_report(sk);
00365 }
else {
00366 spin_unlock_irq(&sk->
error_queue.
lock);
00367 }
00368
00369 out_free_skb:
00370
kfree_skb(skb);
00371 out:
00372
return err;
00373 }
00374
00375
00376
00377
00378
00379
00380
00381 int ip_setsockopt(
struct sock *sk,
int level,
int optname,
char *optval,
int optlen)
00382 {
00383
int val=0,err;
00384
00385
if (level != SOL_IP)
00386
return -ENOPROTOOPT;
00387
00388
if (((1<<optname) & ((1<<
IP_PKTINFO) | (1<<
IP_RECVTTL) |
00389 (1<<
IP_RECVOPTS) | (1<<
IP_RECVTOS) |
00390 (1<<
IP_RETOPTS) | (1<<
IP_TOS) |
00391 (1<<
IP_TTL) | (1<<
IP_HDRINCL) |
00392 (1<<
IP_MTU_DISCOVER) | (1<<
IP_RECVERR) |
00393 (1<<
IP_ROUTER_ALERT) | (1<<
IP_FREEBIND))) ||
00394 optname ==
IP_MULTICAST_TTL ||
00395 optname ==
IP_MULTICAST_LOOP) {
00396
if (optlen >=
sizeof(
int)) {
00397
if (get_user(val, (
int *) optval))
00398
return -EFAULT;
00399 }
else if (optlen >=
sizeof(
char)) {
00400
unsigned char ucval;
00401
00402
if (get_user(ucval, (
unsigned char *) optval))
00403
return -EFAULT;
00404 val = (
int) ucval;
00405 }
00406 }
00407
00408
00409
00410
#ifdef CONFIG_IP_MROUTE
00411
if (optname >= MRT_BASE && optname <= (MRT_BASE + 10))
00412
return ip_mroute_setsockopt(sk,optname,optval,optlen);
00413
#endif
00414
00415 err = 0;
00416
lock_sock(sk);
00417
00418
switch (optname) {
00419
case IP_OPTIONS:
00420 {
00421
struct ip_options * opt = NULL;
00422
if (optlen > 40 || optlen < 0)
00423
goto e_inval;
00424 err =
ip_options_get(&opt, optval, optlen, 1);
00425
if (err)
00426
break;
00427
if (sk->
type == SOCK_STREAM) {
00428
struct tcp_opt *tp = &sk->
tp_pinfo.af_tcp;
00429
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
00430
if (sk->
family == PF_INET ||
00431 (!((1<<sk->
state)&(TCPF_LISTEN|TCPF_CLOSE))
00432 && sk->
daddr != LOOPBACK4_IPV6)) {
00433
#endif
00434
if (opt)
00435 tp->ext_header_len = opt->optlen;
00436
tcp_sync_mss(sk, tp->pmtu_cookie);
00437
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
00438
}
00439
#endif
00440
}
00441 opt = xchg(&sk->
protinfo.af_inet.opt, opt);
00442
if (opt)
00443 kfree(opt);
00444
break;
00445 }
00446
case IP_PKTINFO:
00447
if (val)
00448 sk->
protinfo.af_inet.cmsg_flags |=
IP_CMSG_PKTINFO;
00449
else
00450 sk->
protinfo.af_inet.cmsg_flags &= ~
IP_CMSG_PKTINFO;
00451
break;
00452
case IP_RECVTTL:
00453
if (val)
00454 sk->
protinfo.af_inet.cmsg_flags |=
IP_CMSG_TTL;
00455
else
00456 sk->
protinfo.af_inet.cmsg_flags &= ~
IP_CMSG_TTL;
00457
break;
00458
case IP_RECVTOS:
00459
if (val)
00460 sk->
protinfo.af_inet.cmsg_flags |=
IP_CMSG_TOS;
00461
else
00462 sk->
protinfo.af_inet.cmsg_flags &= ~
IP_CMSG_TOS;
00463
break;
00464
case IP_RECVOPTS:
00465
if (val)
00466 sk->
protinfo.af_inet.cmsg_flags |=
IP_CMSG_RECVOPTS;
00467
else
00468 sk->
protinfo.af_inet.cmsg_flags &= ~
IP_CMSG_RECVOPTS;
00469
break;
00470
case IP_RETOPTS:
00471
if (val)
00472 sk->
protinfo.af_inet.cmsg_flags |=
IP_CMSG_RETOPTS;
00473
else
00474 sk->
protinfo.af_inet.cmsg_flags &= ~
IP_CMSG_RETOPTS;
00475
break;
00476
case IP_TOS:
00477
if (sk->
type == SOCK_STREAM) {
00478 val &= ~3;
00479 val |= sk->
protinfo.af_inet.tos & 3;
00480 }
00481
if (
IPTOS_PREC(val) >=
IPTOS_PREC_CRITIC_ECP &&
00482 !capable(CAP_NET_ADMIN)) {
00483 err = -EPERM;
00484
break;
00485 }
00486
if (sk->
protinfo.af_inet.tos != val) {
00487 sk->
protinfo.af_inet.tos=val;
00488 sk->
priority =
rt_tos2priority(val);
00489
sk_dst_reset(sk);
00490 }
00491
break;
00492
case IP_TTL:
00493
if (optlen<1)
00494
goto e_inval;
00495
if(val==-1)
00496 val =
sysctl_ip_default_ttl;
00497
if(val<1||val>255)
00498
goto e_inval;
00499 sk->
protinfo.af_inet.ttl=val;
00500
break;
00501
case IP_HDRINCL:
00502
if(sk->
type!=SOCK_RAW) {
00503 err = -ENOPROTOOPT;
00504
break;
00505 }
00506 sk->
protinfo.af_inet.hdrincl=val?1:0;
00507
break;
00508
case IP_MTU_DISCOVER:
00509
if (val<0 || val>2)
00510
goto e_inval;
00511 sk->
protinfo.af_inet.pmtudisc = val;
00512
break;
00513
case IP_RECVERR:
00514 sk->
protinfo.af_inet.recverr = !!val;
00515
if (!val)
00516
skb_queue_purge(&sk->
error_queue);
00517
break;
00518
case IP_MULTICAST_TTL:
00519
if (sk->
type == SOCK_STREAM)
00520
goto e_inval;
00521
if (optlen<1)
00522
goto e_inval;
00523
if (val==-1)
00524 val = 1;
00525
if (val < 0 || val > 255)
00526
goto e_inval;
00527 sk->
protinfo.af_inet.mc_ttl=val;
00528
break;
00529
case IP_MULTICAST_LOOP:
00530
if (optlen<1)
00531
goto e_inval;
00532 sk->
protinfo.af_inet.mc_loop = val ? 1 : 0;
00533
break;
00534
case IP_MULTICAST_IF:
00535 {
00536
struct ip_mreqn mreq;
00537
struct net_device *dev = NULL;
00538
00539
if (sk->
type == SOCK_STREAM)
00540
goto e_inval;
00541
00542
00543
00544
00545 err = -EFAULT;
00546
if (optlen >=
sizeof(
struct ip_mreqn)) {
00547
if (copy_from_user(&mreq,optval,
sizeof(mreq)))
00548
break;
00549 }
else {
00550 memset(&mreq, 0,
sizeof(mreq));
00551
if (optlen >=
sizeof(
struct in_addr) &&
00552 copy_from_user(&mreq.imr_address,optval,
sizeof(
struct in_addr)))
00553
break;
00554 }
00555
00556
if (!mreq.
imr_ifindex) {
00557
if (mreq.
imr_address.
s_addr ==
INADDR_ANY) {
00558 sk->
protinfo.af_inet.mc_index = 0;
00559 sk->
protinfo.af_inet.mc_addr = 0;
00560 err = 0;
00561
break;
00562 }
00563 dev =
ip_dev_find(mreq.
imr_address.
s_addr);
00564
if (dev) {
00565 mreq.
imr_ifindex = dev->ifindex;
00566
dev_put(dev);
00567 }
00568 }
else
00569 dev =
__dev_get_by_index(mreq.
imr_ifindex);
00570
00571
00572 err = -EADDRNOTAVAIL;
00573
if (!dev)
00574
break;
00575
00576 err = -EINVAL;
00577
if (sk->
bound_dev_if && mreq.
imr_ifindex != sk->
bound_dev_if)
00578
break;
00579
00580 sk->
protinfo.af_inet.mc_index = mreq.
imr_ifindex;
00581 sk->
protinfo.af_inet.mc_addr = mreq.
imr_address.
s_addr;
00582 err = 0;
00583
break;
00584 }
00585
00586
case IP_ADD_MEMBERSHIP:
00587
case IP_DROP_MEMBERSHIP:
00588 {
00589
struct ip_mreqn mreq;
00590
00591
if (optlen <
sizeof(
struct ip_mreq))
00592 goto e_inval;
00593 err = -EFAULT;
00594
if (optlen >=
sizeof(
struct ip_mreqn)) {
00595
if(copy_from_user(&mreq,optval,
sizeof(mreq)))
00596
break;
00597 }
else {
00598 memset(&mreq, 0,
sizeof(mreq));
00599
if (copy_from_user(&mreq,optval,
sizeof(
struct ip_mreq)))
00600
break;
00601 }
00602
00603
if (optname ==
IP_ADD_MEMBERSHIP)
00604 err =
ip_mc_join_group(sk, &mreq);
00605
else
00606 err =
ip_mc_leave_group(sk, &mreq);
00607
break;
00608 }
00609
case IP_MSFILTER:
00610 {
00611
struct ip_msfilter *msf;
00612
00613
if (optlen <
IP_MSFILTER_SIZE(0))
00614
goto e_inval;
00615 msf = (
struct ip_msfilter *)kmalloc(optlen, GFP_KERNEL);
00616
if (msf == 0) {
00617 err = -ENOBUFS;
00618
break;
00619 }
00620 err = -EFAULT;
00621
if (copy_from_user(msf, optval, optlen)) {
00622 kfree(msf);
00623
break;
00624 }
00625 err =
ip_mc_msfilter(sk, msf, 0);
00626 kfree(msf);
00627
break;
00628 }
00629
case IP_BLOCK_SOURCE:
00630
case IP_UNBLOCK_SOURCE:
00631
case IP_ADD_SOURCE_MEMBERSHIP:
00632
case IP_DROP_SOURCE_MEMBERSHIP:
00633 {
00634
struct ip_mreq_source mreqs;
00635
int omode, add;
00636
00637
if (optlen !=
sizeof(
struct ip_mreq_source))
00638 goto e_inval;
00639
if (copy_from_user(&mreqs, optval,
sizeof(mreqs))) {
00640 err = -EFAULT;
00641
break;
00642 }
00643
if (optname ==
IP_BLOCK_SOURCE) {
00644 omode =
MCAST_EXCLUDE;
00645 add = 1;
00646 }
else if (optname ==
IP_UNBLOCK_SOURCE) {
00647 omode =
MCAST_EXCLUDE;
00648 add = 0;
00649 }
else if (optname ==
IP_ADD_SOURCE_MEMBERSHIP) {
00650
struct ip_mreqn mreq;
00651
00652 mreq.
imr_multiaddr.
s_addr = mreqs.imr_multiaddr;
00653 mreq.
imr_address.
s_addr = mreqs.imr_interface;
00654 mreq.
imr_ifindex = 0;
00655 err =
ip_mc_join_group(sk, &mreq);
00656
if (err)
00657
break;
00658 omode =
MCAST_INCLUDE;
00659 add = 1;
00660 }
else {
00661 omode =
MCAST_INCLUDE;
00662 add = 0;
00663 }
00664 err =
ip_mc_source(add, omode, sk, &mreqs, 0);
00665
break;
00666 }
00667
case MCAST_JOIN_GROUP:
00668
case MCAST_LEAVE_GROUP:
00669 {
00670
struct group_req greq;
00671
struct sockaddr_in *psin;
00672
struct ip_mreqn mreq;
00673
00674
if (optlen <
sizeof(
struct group_req))
00675 goto e_inval;
00676 err = -EFAULT;
00677
if(copy_from_user(&greq, optval,
sizeof(greq)))
00678
break;
00679 psin = (
struct sockaddr_in *)&greq.
gr_group;
00680
if (psin->sin_family != AF_INET)
00681
goto e_inval;
00682 memset(&mreq, 0,
sizeof(mreq));
00683 mreq.imr_multiaddr = psin->sin_addr;
00684 mreq.imr_ifindex = greq.gr_interface;
00685
00686
if (optname ==
MCAST_JOIN_GROUP)
00687 err =
ip_mc_join_group(sk, &mreq);
00688
else
00689 err =
ip_mc_leave_group(sk, &mreq);
00690
break;
00691 }
00692
case MCAST_JOIN_SOURCE_GROUP:
00693
case MCAST_LEAVE_SOURCE_GROUP:
00694
case MCAST_BLOCK_SOURCE:
00695
case MCAST_UNBLOCK_SOURCE:
00696 {
00697
struct group_source_req greqs;
00698
struct ip_mreq_source mreqs;
00699
struct sockaddr_in *psin;
00700
int omode, add;
00701
00702
if (optlen !=
sizeof(
struct group_source_req))
00703 goto e_inval;
00704
if (copy_from_user(&greqs, optval,
sizeof(greqs))) {
00705 err = -EFAULT;
00706
break;
00707 }
00708
if (greqs.gsr_group.ss_family != AF_INET ||
00709 greqs.gsr_source.ss_family != AF_INET) {
00710 err = -EADDRNOTAVAIL;
00711
break;
00712 }
00713 psin = (
struct sockaddr_in *)&greqs.
gsr_group;
00714 mreqs.
imr_multiaddr = psin->sin_addr.s_addr;
00715 psin = (
struct sockaddr_in *)&greqs.gsr_source;
00716 mreqs.
imr_sourceaddr = psin->sin_addr.s_addr;
00717 mreqs.
imr_interface = 0;
00718
00719
if (optname ==
MCAST_BLOCK_SOURCE) {
00720 omode =
MCAST_EXCLUDE;
00721 add = 1;
00722 }
else if (optname ==
MCAST_UNBLOCK_SOURCE) {
00723 omode =
MCAST_EXCLUDE;
00724 add = 0;
00725 }
else if (optname ==
MCAST_JOIN_SOURCE_GROUP) {
00726
struct ip_mreqn mreq;
00727
00728 psin = (
struct sockaddr_in *)&greqs.gsr_group;
00729 mreq.
imr_multiaddr = psin->sin_addr;
00730 mreq.
imr_address.
s_addr = 0;
00731 mreq.
imr_ifindex = greqs.gsr_interface;
00732 err =
ip_mc_join_group(sk, &mreq);
00733
if (err)
00734
break;
00735 omode =
MCAST_INCLUDE;
00736 add = 1;
00737 }
else {
00738 omode =
MCAST_INCLUDE;
00739 add = 0;
00740 }
00741 err =
ip_mc_source(add, omode, sk, &mreqs,
00742 greqs.gsr_interface);
00743
break;
00744 }
00745
case MCAST_MSFILTER:
00746 {
00747
struct sockaddr_in *psin;
00748
struct ip_msfilter *msf = 0;
00749
struct group_filter *gsf = 0;
00750
int msize, i, ifindex;
00751
00752
if (optlen <
GROUP_FILTER_SIZE(0))
00753
goto e_inval;
00754 gsf = (
struct group_filter *)kmalloc(optlen,GFP_KERNEL);
00755
if (gsf == 0) {
00756 err = -ENOBUFS;
00757
break;
00758 }
00759 err = -EFAULT;
00760
if (copy_from_user(gsf, optval, optlen)) {
00761
goto mc_msf_out;
00762 }
00763
if (
GROUP_FILTER_SIZE(gsf->gf_numsrc) < optlen) {
00764 err = EINVAL;
00765
goto mc_msf_out;
00766 }
00767 msize =
IP_MSFILTER_SIZE(gsf->gf_numsrc);
00768 msf = (
struct ip_msfilter *)kmalloc(msize,GFP_KERNEL);
00769
if (msf == 0) {
00770 err = -ENOBUFS;
00771
goto mc_msf_out;
00772 }
00773 ifindex = gsf->gf_interface;
00774 psin = (
struct sockaddr_in *)&gsf->gf_group;
00775
if (psin->sin_family != AF_INET) {
00776 err = -EADDRNOTAVAIL;
00777
goto mc_msf_out;
00778 }
00779 msf->imsf_multiaddr = psin->sin_addr.s_addr;
00780 msf->imsf_interface = 0;
00781 msf->imsf_fmode = gsf->gf_fmode;
00782 msf->imsf_numsrc = gsf->gf_numsrc;
00783 err = -EADDRNOTAVAIL;
00784
for (i=0; i<gsf->gf_numsrc; ++i) {
00785 psin = (
struct sockaddr_in *)&gsf->gf_slist[i];
00786
00787
if (psin->sin_family != AF_INET)
00788
goto mc_msf_out;
00789 msf->imsf_slist[i] = psin->sin_addr.s_addr;
00790 }
00791 kfree(gsf);
00792 gsf = 0;
00793
00794 err =
ip_mc_msfilter(sk, msf, ifindex);
00795 mc_msf_out:
00796
if (msf)
00797 kfree(msf);
00798
if (gsf)
00799 kfree(gsf);
00800
break;
00801 }
00802
case IP_ROUTER_ALERT:
00803 err =
ip_ra_control(sk, val ? 1 : 0, NULL);
00804
break;
00805
00806
case IP_FREEBIND:
00807
if (optlen<1)
00808
goto e_inval;
00809 sk->
protinfo.af_inet.freebind = !!val;
00810
break;
00811
00812
default:
00813
#ifdef CONFIG_NETFILTER
00814
err =
nf_setsockopt(sk, PF_INET, optname, optval,
00815 optlen);
00816
#else
00817
err = -ENOPROTOOPT;
00818
#endif
00819
break;
00820 }
00821
release_sock(sk);
00822
return err;
00823
00824 e_inval:
00825
release_sock(sk);
00826
return -EINVAL;
00827 }
00828
00829
00830
00831
00832
00833
00834 int ip_getsockopt(
struct sock *sk,
int level,
int optname,
char *optval,
int *optlen)
00835 {
00836
int val;
00837
int len;
00838
00839
if(level!=SOL_IP)
00840
return -EOPNOTSUPP;
00841
00842
#ifdef CONFIG_IP_MROUTE
00843
if(optname>=MRT_BASE && optname <=MRT_BASE+10)
00844 {
00845
return ip_mroute_getsockopt(sk,optname,optval,optlen);
00846 }
00847
#endif
00848
00849
if(get_user(len,optlen))
00850
return -EFAULT;
00851
if(len < 0)
00852
return -EINVAL;
00853
00854
lock_sock(sk);
00855
00856
switch(optname) {
00857
case IP_OPTIONS:
00858 {
00859
unsigned char optbuf[
sizeof(
struct ip_options)+40];
00860
struct ip_options * opt = (
struct ip_options*)optbuf;
00861 opt->optlen = 0;
00862
if (sk->
protinfo.af_inet.opt)
00863 memcpy(optbuf, sk->
protinfo.af_inet.opt,
00864
sizeof(
struct ip_options)+
00865 sk->
protinfo.af_inet.opt->optlen);
00866
release_sock(sk);
00867
00868
if (opt->optlen == 0)
00869
return put_user(0, optlen);
00870
00871
ip_options_undo(opt);
00872
00873 len = min_t(
unsigned int, len, opt->optlen);
00874
if(put_user(len, optlen))
00875
return -EFAULT;
00876
if(copy_to_user(optval, opt->__data, len))
00877
return -EFAULT;
00878
return 0;
00879 }
00880
case IP_PKTINFO:
00881 val = (sk->
protinfo.af_inet.cmsg_flags &
IP_CMSG_PKTINFO) != 0;
00882
break;
00883
case IP_RECVTTL:
00884 val = (sk->
protinfo.af_inet.cmsg_flags &
IP_CMSG_TTL) != 0;
00885
break;
00886
case IP_RECVTOS:
00887 val = (sk->
protinfo.af_inet.cmsg_flags &
IP_CMSG_TOS) != 0;
00888
break;
00889
case IP_RECVOPTS:
00890 val = (sk->
protinfo.af_inet.cmsg_flags &
IP_CMSG_RECVOPTS) != 0;
00891
break;
00892
case IP_RETOPTS:
00893 val = (sk->
protinfo.af_inet.cmsg_flags &
IP_CMSG_RETOPTS) != 0;
00894
break;
00895
case IP_TOS:
00896 val=sk->
protinfo.af_inet.tos;
00897
break;
00898
case IP_TTL:
00899 val=sk->
protinfo.af_inet.ttl;
00900
break;
00901
case IP_HDRINCL:
00902 val=sk->
protinfo.af_inet.hdrincl;
00903
break;
00904
case IP_MTU_DISCOVER:
00905 val=sk->
protinfo.af_inet.pmtudisc;
00906
break;
00907
case IP_MTU:
00908 {
00909
struct dst_entry *dst;
00910 val = 0;
00911 dst =
sk_dst_get(sk);
00912
if (dst) {
00913 val = dst->pmtu;
00914
dst_release(dst);
00915 }
00916
if (!val) {
00917
release_sock(sk);
00918
return -ENOTCONN;
00919 }
00920
break;
00921 }
00922
case IP_RECVERR:
00923 val=sk->
protinfo.af_inet.recverr;
00924
break;
00925
case IP_MULTICAST_TTL:
00926 val=sk->
protinfo.af_inet.mc_ttl;
00927
break;
00928
case IP_MULTICAST_LOOP:
00929 val=sk->
protinfo.af_inet.mc_loop;
00930
break;
00931
case IP_MULTICAST_IF:
00932 {
00933
struct in_addr addr;
00934 len = min_t(
unsigned int, len,
sizeof(
struct in_addr));
00935 addr.
s_addr = sk->
protinfo.af_inet.mc_addr;
00936
release_sock(sk);
00937
00938
if(put_user(len, optlen))
00939
return -EFAULT;
00940
if(copy_to_user((
void *)optval, &addr, len))
00941
return -EFAULT;
00942
return 0;
00943 }
00944
case IP_MSFILTER:
00945 {
00946
struct ip_msfilter msf;
00947
int err;
00948
00949
if (len <
IP_MSFILTER_SIZE(0)) {
00950
release_sock(sk);
00951
return -EINVAL;
00952 }
00953
if (copy_from_user(&msf, optval,
IP_MSFILTER_SIZE(0))) {
00954
release_sock(sk);
00955
return -EFAULT;
00956 }
00957 err =
ip_mc_msfget(sk, &msf,
00958 (
struct ip_msfilter *)optval, optlen);
00959
release_sock(sk);
00960
return err;
00961 }
00962
case MCAST_MSFILTER:
00963 {
00964
struct group_filter gsf;
00965
int err;
00966
00967
if (len <
GROUP_FILTER_SIZE(0)) {
00968
release_sock(sk);
00969
return -EINVAL;
00970 }
00971
if (copy_from_user(&gsf, optval,
GROUP_FILTER_SIZE(0))) {
00972
release_sock(sk);
00973
return -EFAULT;
00974 }
00975 err =
ip_mc_gsfget(sk, &gsf,
00976 (
struct group_filter *)optval, optlen);
00977
release_sock(sk);
00978
return err;
00979 }
00980
case IP_PKTOPTIONS:
00981 {
00982
struct msghdr msg;
00983
00984
release_sock(sk);
00985
00986
if (sk->
type != SOCK_STREAM)
00987
return -ENOPROTOOPT;
00988
00989 msg.msg_control = optval;
00990 msg.msg_controllen = len;
00991 msg.msg_flags = 0;
00992
00993
if (sk->
protinfo.af_inet.cmsg_flags&
IP_CMSG_PKTINFO) {
00994
struct in_pktinfo info;
00995
00996 info.
ipi_addr.
s_addr = sk->
rcv_saddr;
00997 info.
ipi_spec_dst.
s_addr = sk->
rcv_saddr;
00998 info.
ipi_ifindex = sk->
protinfo.af_inet.mc_index;
00999
put_cmsg(&msg, SOL_IP,
IP_PKTINFO,
sizeof(info), &info);
01000 }
01001
if (sk->
protinfo.af_inet.cmsg_flags&
IP_CMSG_TTL) {
01002
int hlim = sk->
protinfo.af_inet.mc_ttl;
01003
put_cmsg(&msg, SOL_IP,
IP_TTL,
sizeof(hlim), &hlim);
01004 }
01005 len -= msg.msg_controllen;
01006
return put_user(len, optlen);
01007 }
01008
case IP_FREEBIND:
01009 val = sk->
protinfo.af_inet.freebind;
01010
break;
01011
default:
01012
#ifdef CONFIG_NETFILTER
01013
val =
nf_getsockopt(sk, PF_INET, optname, optval,
01014 &len);
01015
release_sock(sk);
01016
if (val >= 0)
01017 val = put_user(len, optlen);
01018
return val;
01019
#else
01020
release_sock(sk);
01021
return -ENOPROTOOPT;
01022
#endif
01023
}
01024
release_sock(sk);
01025
01026
if (len < sizeof(int) && len > 0 && val>=0 && val<255) {
01027
unsigned char ucval = (
unsigned char)val;
01028 len = 1;
01029
if(put_user(len, optlen))
01030
return -EFAULT;
01031
if(copy_to_user(optval,&ucval,1))
01032
return -EFAULT;
01033 }
else {
01034 len = min_t(
unsigned int,
sizeof(
int), len);
01035
if(put_user(len, optlen))
01036
return -EFAULT;
01037
if(copy_to_user(optval,&val,len))
01038
return -EFAULT;
01039 }
01040
return 0;
01041 }