OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [net/] [ipv4/] [ip_sockglue.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
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
 * Authors:     see ip.c
9
 *
10
 * Fixes:
11
 *              Many            :       Split from ip.c , see ip.c for history.
12
 *              Martin Mares    :       TOS setting fixed.
13
 *              Alan Cox        :       Fixed a couple of oopses in Martin's
14
 *                                      TOS tweaks.
15
 *              Elliot Poger    :       Added support for SO_BINDTODEVICE.
16
 */
17
 
18
 
19
#include <linux/config.h>
20
#include <linux/types.h>
21
#include <linux/mm.h>
22
#include <linux/sched.h>
23
#include <linux/skbuff.h>
24
#include <linux/ip.h>
25
#include <linux/icmp.h>
26
#include <linux/netdevice.h>
27
#include <net/sock.h>
28
#include <net/ip.h>
29
#include <net/icmp.h>
30
#include <linux/tcp.h>
31
#include <linux/udp.h>
32
#include <linux/firewall.h>
33
#include <linux/ip_fw.h>
34
#include <net/checksum.h>
35
#include <linux/route.h>
36
#include <linux/mroute.h>
37
#include <net/route.h>
38
 
39
#include <asm/segment.h>
40
 
41
#ifdef CONFIG_IP_MULTICAST
42
 
43
/*
44
 *      Write an multicast group list table for the IGMP daemon to
45
 *      read.
46
 */
47
 
48
int ip_mc_procinfo(char *buffer, char **start, off_t offset, int length, int dummy)
49
{
50
        off_t pos=0, begin=0;
51
        struct ip_mc_list *im;
52
        unsigned long flags;
53
        int len=0;
54
        struct device *dev;
55
 
56
        len=sprintf(buffer,"Device    : Count\tGroup    Users Timer\n");
57
        save_flags(flags);
58
        cli();
59
 
60
        for(dev = dev_base; dev; dev = dev->next)
61
        {
62
                if((dev->flags&IFF_UP)&&(dev->flags&IFF_MULTICAST))
63
                {
64
                        len+=sprintf(buffer+len,"%-10s: %5d\n",
65
                                        dev->name, dev->mc_count);
66
                        for(im = dev->ip_mc_list; im; im = im->next)
67
                        {
68
                                len+=sprintf(buffer+len,
69
                                        "\t\t\t%08lX %5d %d:%08lX\n",
70
                                        im->multiaddr, im->users,
71
                                        im->tm_running, im->timer.expires-jiffies);
72
                                pos=begin+len;
73
                                if(pos<offset)
74
                                {
75
                                        len=0;
76
                                        begin=pos;
77
                                }
78
                                if(pos>offset+length)
79
                                        break;
80
                        }
81
                }
82
        }
83
        restore_flags(flags);
84
        *start=buffer+(offset-begin);
85
        len-=(offset-begin);
86
        if(len>length)
87
                len=length;
88
        return len;
89
}
90
 
91
 
92
/*
93
 *      Socket option code for IP. This is the end of the line after any TCP,UDP etc options on
94
 *      an IP socket.
95
 *
96
 *      We implement IP_TOS (type of service), IP_TTL (time to live).
97
 */
98
 
99
static struct device *ip_mc_find_devfor(unsigned long addr)
100
{
101
        struct device *dev;
102
        for(dev = dev_base; dev; dev = dev->next)
103
        {
104
                if((dev->flags&IFF_UP)&&(dev->flags&IFF_MULTICAST)&&
105
                        (dev->pa_addr==addr))
106
                        return dev;
107
        }
108
 
109
        return NULL;
110
}
111
 
112
#endif
113
 
114
int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen)
115
{
116
        int val,err;
117
        unsigned char ucval;
118
#if defined(CONFIG_IP_FIREWALL) || defined(CONFIG_IP_ACCT)
119
        struct ip_fw tmp_fw;
120
#endif  
121
        if (optval == NULL)
122
        {
123
                val=0;
124
                ucval=0;
125
        }
126
        else
127
        {
128
                err=verify_area(VERIFY_READ, optval, sizeof(int));
129
                if(err)
130
                        return err;
131
                val = get_user((int *) optval);
132
                ucval=get_user((unsigned char *) optval);
133
        }
134
 
135
        if(level!=SOL_IP)
136
                return -EOPNOTSUPP;
137
#ifdef CONFIG_IP_MROUTE
138
        if(optname>=MRT_BASE && optname <=MRT_BASE+10)
139
        {
140
                return ip_mroute_setsockopt(sk,optname,optval,optlen);
141
        }
142
#endif
143
 
144
        switch(optname)
145
        {
146
                case IP_OPTIONS:
147
                  {
148
                          struct options * opt = NULL;
149
                          struct options * old_opt;
150
                          if (optlen > 40 || optlen < 0)
151
                                return -EINVAL;
152
                          err = verify_area(VERIFY_READ, optval, optlen);
153
                          if (err)
154
                                return err;
155
                          opt = kmalloc(sizeof(struct options)+((optlen+3)&~3), GFP_KERNEL);
156
                          if (!opt)
157
                                return -ENOMEM;
158
                          memset(opt, 0, sizeof(struct options));
159
                          if (optlen)
160
                                memcpy_fromfs(opt->__data, optval, optlen);
161
                          while (optlen & 3)
162
                                opt->__data[optlen++] = IPOPT_END;
163
                          opt->optlen = optlen;
164
                          opt->is_data = 1;
165
                          opt->is_setbyuser = 1;
166
                          if (optlen && ip_options_compile(opt, NULL))
167
                          {
168
                                  kfree_s(opt, sizeof(struct options) + optlen);
169
                                  return -EINVAL;
170
                          }
171
                          /*
172
                           * ANK: I'm afraid that receive handler may change
173
                           * options from under us.
174
                           */
175
                          cli();
176
                          old_opt = sk->opt;
177
                          sk->opt = opt;
178
                          sti();
179
                          if (old_opt)
180
                                kfree_s(old_opt, sizeof(struct optlen) + old_opt->optlen);
181
                          return 0;
182
                  }
183
                case IP_TOS:                    /* This sets both TOS and Precedence */
184
                        if (val & ~0xfe)        /* Reject setting of unused bits */
185
                                return -EINVAL;
186
                        if ((val>>5) > 4 && !suser())   /* Only root can set Prec>4 */
187
                                return -EPERM;
188
                        sk->ip_tos=val;
189
                        switch (val & 0x1E) {
190
                                case IPTOS_LOWDELAY:
191
                                        sk->priority=SOPRI_INTERACTIVE;
192
                                        break;
193
                                case IPTOS_THROUGHPUT:
194
                                case IPTOS_MINCOST:
195
                                        sk->priority=SOPRI_BACKGROUND;
196
                                        break;
197
                                default:
198
                                        sk->priority=SOPRI_NORMAL;
199
                                        break;
200
                        }
201
                        return 0;
202
                case IP_TTL:
203
                        if(val<1||val>255)
204
                                return -EINVAL;
205
                        sk->ip_ttl=val;
206
                        return 0;
207
                case IP_HDRINCL:
208
                        if(sk->type!=SOCK_RAW)
209
                                return -ENOPROTOOPT;
210
                        sk->ip_hdrincl=val?1:0;
211
                        return 0;
212
#ifdef CONFIG_IP_MULTICAST
213
                case IP_MULTICAST_TTL:
214
                {
215
                        sk->ip_mc_ttl=(int)ucval;
216
                        return 0;
217
                }
218
                case IP_MULTICAST_LOOP:
219
                {
220
                        if(ucval!=0 && ucval!=1)
221
                                 return -EINVAL;
222
                        sk->ip_mc_loop=(int)ucval;
223
                        return 0;
224
                }
225
                case IP_MULTICAST_IF:
226
                {
227
                        struct in_addr addr;
228
                        struct device *dev=NULL;
229
 
230
                        /*
231
                         *      Check the arguments are allowable
232
                         */
233
 
234
                        err=verify_area(VERIFY_READ, optval, sizeof(addr));
235
                        if(err)
236
                                return err;
237
 
238
                        memcpy_fromfs(&addr,optval,sizeof(addr));
239
 
240
 
241
                        /*
242
                         *      What address has been requested
243
                         */
244
 
245
                        if(addr.s_addr==INADDR_ANY)     /* Default */
246
                        {
247
                                sk->ip_mc_name[0]=0;
248
                                return 0;
249
                        }
250
 
251
                        /*
252
                         *      Find the device
253
                         */
254
 
255
                        dev=ip_mc_find_devfor(addr.s_addr);
256
 
257
                        /*
258
                         *      Did we find one
259
                         */
260
 
261
                        if(dev)
262
                        {
263
                                strcpy(sk->ip_mc_name,dev->name);
264
                                return 0;
265
                        }
266
                        return -EADDRNOTAVAIL;
267
                }
268
 
269
                case IP_ADD_MEMBERSHIP:
270
                {
271
 
272
/*
273
 *      FIXME: Add/Del membership should have a semaphore protecting them from re-entry
274
 */
275
                        struct ip_mreq mreq;
276
                        struct rtable *rt;
277
                        struct device *dev=NULL;
278
 
279
                        /*
280
                         *      Check the arguments.
281
                         */
282
 
283
                        err=verify_area(VERIFY_READ, optval, sizeof(mreq));
284
                        if(err)
285
                                return err;
286
 
287
                        memcpy_fromfs(&mreq,optval,sizeof(mreq));
288
 
289
                        /*
290
                         *      Get device for use later
291
                         */
292
 
293
                        if(mreq.imr_interface.s_addr==INADDR_ANY)
294
                        {
295
                                /*
296
                                 *      Not set so scan.
297
                                 */
298
                                if((rt=ip_rt_route(mreq.imr_multiaddr.s_addr,0,sk->bound_device))!=NULL)
299
                                {
300
                                        dev=rt->rt_dev;
301
                                        atomic_dec(&rt->rt_use);
302
                                        ip_rt_put(rt);
303
                                }
304
                        }
305
                        else
306
                        {
307
                                /*
308
                                 *      Find a suitable device.
309
                                 */
310
 
311
                                dev=ip_mc_find_devfor(mreq.imr_interface.s_addr);
312
                        }
313
 
314
                        /*
315
                         *      No device, no cookies.
316
                         */
317
 
318
                        if(!dev)
319
                                return -ENODEV;
320
 
321
                        /*
322
                         *      Join group.
323
                         */
324
 
325
                        return ip_mc_join_group(sk,dev,mreq.imr_multiaddr.s_addr);
326
                }
327
 
328
                case IP_DROP_MEMBERSHIP:
329
                {
330
                        struct ip_mreq mreq;
331
                        struct rtable *rt;
332
                        struct device *dev=NULL;
333
 
334
                        /*
335
                         *      Check the arguments
336
                         */
337
 
338
                        err=verify_area(VERIFY_READ, optval, sizeof(mreq));
339
                        if(err)
340
                                return err;
341
 
342
                        memcpy_fromfs(&mreq,optval,sizeof(mreq));
343
 
344
                        /*
345
                         *      Get device for use later
346
                         */
347
 
348
                        if(mreq.imr_interface.s_addr==INADDR_ANY)
349
                        {
350
                                if((rt=ip_rt_route(mreq.imr_multiaddr.s_addr,0,sk->bound_device))!=NULL)
351
                                {
352
                                        dev=rt->rt_dev;
353
                                        atomic_dec(&rt->rt_use);
354
                                        ip_rt_put(rt);
355
                                }
356
                        }
357
                        else
358
                        {
359
 
360
                                dev=ip_mc_find_devfor(mreq.imr_interface.s_addr);
361
                        }
362
 
363
                        /*
364
                         *      Did we find a suitable device.
365
                         */
366
 
367
                        if(!dev)
368
                                return -ENODEV;
369
 
370
                        /*
371
                         *      Leave group
372
                         */
373
 
374
                        return ip_mc_leave_group(sk,dev,mreq.imr_multiaddr.s_addr);
375
                }
376
#endif                  
377
#ifdef CONFIG_IP_FIREWALL
378
                case IP_FW_INSERT_IN:
379
                case IP_FW_INSERT_OUT:
380
                case IP_FW_INSERT_FWD:
381
                case IP_FW_APPEND_IN:
382
                case IP_FW_APPEND_OUT:
383
                case IP_FW_APPEND_FWD:
384
                case IP_FW_DELETE_IN:
385
                case IP_FW_DELETE_OUT:
386
                case IP_FW_DELETE_FWD:
387
                case IP_FW_CHECK_IN:
388
                case IP_FW_CHECK_OUT:
389
                case IP_FW_CHECK_FWD:
390
                case IP_FW_FLUSH_IN:
391
                case IP_FW_FLUSH_OUT:
392
                case IP_FW_FLUSH_FWD:
393
                case IP_FW_ZERO_IN:
394
                case IP_FW_ZERO_OUT:
395
                case IP_FW_ZERO_FWD:
396
                case IP_FW_POLICY_IN:
397
                case IP_FW_POLICY_OUT:
398
                case IP_FW_POLICY_FWD:
399
                case IP_FW_MASQ_TIMEOUTS:
400
                        if(!suser())
401
                                return -EPERM;
402
                        if(optlen>sizeof(tmp_fw) || optlen<1)
403
                                return -EINVAL;
404
                        err=verify_area(VERIFY_READ,optval,optlen);
405
                        if(err)
406
                                return err;
407
                        memcpy_fromfs(&tmp_fw,optval,optlen);
408
                        err=ip_fw_ctl(optname, &tmp_fw,optlen);
409
                        return -err;    /* -0 is 0 after all */
410
 
411
#endif
412
#ifdef CONFIG_IP_MASQUERADE_IPAUTOFW
413
                case IP_AUTOFW_ADD:
414
                case IP_AUTOFW_DEL:
415
                case IP_AUTOFW_FLUSH:
416
                        if(!suser())
417
                                return -EPERM;
418
                        if(optlen>sizeof(tmp_fw) || optlen<1)
419
                                return -EINVAL;
420
                        err=verify_area(VERIFY_READ,optval,optlen);
421
                        if(err)
422
                                return err;
423
                        memcpy_fromfs(&tmp_fw,optval,optlen);
424
                        err=ip_autofw_ctl(optname, &tmp_fw,optlen);
425
                        return -err;    /* -0 is 0 after all */
426
 
427
#endif
428
#ifdef CONFIG_IP_MASQUERADE_IPPORTFW
429
               case IP_PORTFW_ADD:
430
               case IP_PORTFW_DEL:
431
               case IP_PORTFW_FLUSH:
432
                       if(!suser())
433
                               return -EPERM;
434
                       if(optlen>sizeof(tmp_fw) || optlen<1)
435
                               return -EINVAL;
436
                       err=verify_area(VERIFY_READ,optval,optlen);
437
                       if(err)
438
                               return err;
439
                       memcpy_fromfs(&tmp_fw,optval,optlen);
440
                       err=ip_portfw_ctl(optname, &tmp_fw,optlen);
441
                       return -err;    /* -0 is 0 after all */
442
 
443
#endif
444
#ifdef CONFIG_IP_ACCT
445
                case IP_ACCT_INSERT:
446
                case IP_ACCT_APPEND:
447
                case IP_ACCT_DELETE:
448
                case IP_ACCT_FLUSH:
449
                case IP_ACCT_ZERO:
450
                        if(!suser())
451
                                return -EPERM;
452
                        if(optlen>sizeof(tmp_fw) || optlen<1)
453
                                return -EINVAL;
454
                        err=verify_area(VERIFY_READ,optval,optlen);
455
                        if(err)
456
                                return err;
457
                        memcpy_fromfs(&tmp_fw, optval,optlen);
458
                        err=ip_acct_ctl(optname, &tmp_fw,optlen);
459
                        return -err;    /* -0 is 0 after all */
460
#endif
461
                /* IP_OPTIONS and friends go here eventually */
462
                default:
463
                        return(-ENOPROTOOPT);
464
        }
465
}
466
 
467
/*
468
 *      Get the options. Note for future reference. The GET of IP options gets the
469
 *      _received_ ones. The set sets the _sent_ ones.
470
 */
471
 
472
int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen)
473
{
474
        int val,err;
475
 
476
        if(level!=SOL_IP)
477
                return -EOPNOTSUPP;
478
 
479
#ifdef CONFIG_IP_MROUTE
480
        if(optname>=MRT_BASE && optname <=MRT_BASE+10)
481
        {
482
                return ip_mroute_getsockopt(sk,optname,optval,optlen);
483
        }
484
#endif
485
 
486
        switch(optname)
487
        {
488
                case IP_OPTIONS:
489
                        {
490
                                unsigned char optbuf[sizeof(struct options)+40];
491
                                struct options * opt = (struct options*)optbuf;
492
                                err = verify_area(VERIFY_WRITE, optlen, sizeof(int));
493
                                if (err)
494
                                        return err;
495
                                cli();
496
                                opt->optlen = 0;
497
                                if (sk->opt)
498
                                        memcpy(optbuf, sk->opt, sizeof(struct options)+sk->opt->optlen);
499
                                sti();
500
                                if (opt->optlen == 0)
501
                                {
502
                                        put_fs_long(0,(unsigned long *) optlen);
503
                                        return 0;
504
                                }
505
                                err = verify_area(VERIFY_WRITE, optval, opt->optlen);
506
                                if (err)
507
                                        return err;
508
/*
509
 * Now we should undo all the changes done by ip_options_compile().
510
 */
511
                                if (opt->srr)
512
                                {
513
                                        unsigned  char * optptr = opt->__data+opt->srr-sizeof(struct  iphdr);
514
                                        memmove(optptr+7, optptr+3, optptr[1]-7);
515
                                        memcpy(optptr+3, &opt->faddr, 4);
516
                                }
517
                                if (opt->rr_needaddr)
518
                                {
519
                                        unsigned  char * optptr = opt->__data+opt->rr-sizeof(struct  iphdr);
520
                                        memset(&optptr[optptr[2]-1], 0, 4);
521
                                        optptr[2] -= 4;
522
                                }
523
                                if (opt->ts)
524
                                {
525
                                        unsigned  char * optptr = opt->__data+opt->ts-sizeof(struct  iphdr);
526
                                        if (opt->ts_needtime)
527
                                        {
528
                                                memset(&optptr[optptr[2]-1], 0, 4);
529
                                                optptr[2] -= 4;
530
                                        }
531
                                        if (opt->ts_needaddr)
532
                                        {
533
                                                memset(&optptr[optptr[2]-1], 0, 4);
534
                                                optptr[2] -= 4;
535
                                        }
536
                                }
537
                                put_fs_long(opt->optlen, (unsigned long *) optlen);
538
                                memcpy_tofs(optval, opt->__data, opt->optlen);
539
                        }
540
                        return 0;
541
                case IP_TOS:
542
                        val=sk->ip_tos;
543
                        break;
544
                case IP_TTL:
545
                        val=sk->ip_ttl;
546
                        break;
547
                case IP_HDRINCL:
548
                        val=sk->ip_hdrincl;
549
                        break;
550
#ifdef CONFIG_IP_MULTICAST                      
551
                case IP_MULTICAST_TTL:
552
                        val=sk->ip_mc_ttl;
553
                        break;
554
                case IP_MULTICAST_LOOP:
555
                        val=sk->ip_mc_loop;
556
                        break;
557
                case IP_MULTICAST_IF:
558
                {
559
                        struct device *dev;
560
                        struct in_addr ia;
561
 
562
                        err=verify_area(VERIFY_WRITE, optlen, sizeof(int));
563
                        if(err)
564
                                return err;
565
                        err=verify_area(VERIFY_WRITE, optval, sizeof(ia));
566
                        if(err)
567
                                return err;
568
 
569
                        if(*sk->ip_mc_name)
570
                        {
571
                                dev=dev_get(sk->ip_mc_name);
572
                                /* Someone ran off with the interface, its probably
573
                                   been downed. */
574
                                if(dev==NULL)
575
                                        return -ENODEV;
576
                                ia.s_addr = dev->pa_addr;
577
                        }
578
                        else
579
                                ia.s_addr = 0L;
580
 
581
                        put_user(sizeof(ia),(int *) optlen);
582
                        memcpy_tofs((void *)optval, &ia, sizeof(ia));
583
                        return 0;
584
                }
585
#endif
586
                default:
587
                        return(-ENOPROTOOPT);
588
        }
589
        err=verify_area(VERIFY_WRITE, optlen, sizeof(int));
590
        if(err)
591
                return err;
592
        put_user(sizeof(int),(int *) optlen);
593
 
594
        err=verify_area(VERIFY_WRITE, optval, sizeof(int));
595
        if(err)
596
                return err;
597
        put_user(val,(int *) optval);
598
 
599
        return(0);
600
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.