Annotation of linux/net/tcp/raw.c, revision 1.1.1.1

1.1       root        1: /* raw.c - implements raw ip sockets. */
                      2: /*
                      3:     Copyright (C) 1992  Ross Biro
                      4: 
                      5:     This program is free software; you can redistribute it and/or modify
                      6:     it under the terms of the GNU General Public License as published by
                      7:     the Free Software Foundation; either version 2, or (at your option)
                      8:     any later version.
                      9: 
                     10:     This program is distributed in the hope that it will be useful,
                     11:     but WITHOUT ANY WARRANTY; without even the implied warranty of
                     12:     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     13:     GNU General Public License for more details.
                     14: 
                     15:     You should have received a copy of the GNU General Public License
                     16:     along with this program; if not, write to the Free Software
                     17:     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
                     18: 
                     19:     The Author may be reached as [email protected] or
                     20:     C/O Department of Mathematics; Stanford University; Stanford, CA 94305
                     21: */
                     22: 
                     23: #include <linux/types.h>
                     24: #include <linux/sched.h>
                     25: #include <linux/fcntl.h>
                     26: #include <linux/socket.h>
                     27: #include <netinet/in.h>
                     28: #include "timer.h"
                     29: #include "ip.h"
                     30: #include "tcp.h"
                     31: #include "sock.h"
                     32: #include <linux/errno.h>
                     33: #include <linux/timer.h>
                     34: #include <asm/system.h>
                     35: #include <asm/segment.h>
                     36: #include "../kern_sock.h" /* for PRINTK */
                     37: 
                     38: extern struct proto raw_prot;
                     39: 
                     40: static  unsigned long
                     41: min(unsigned long a, unsigned long b)
                     42: {
                     43:    if (a < b) return (a);
                     44:    return (b);
                     45: }
                     46: 
                     47: /* this should be the easiest of all, all we do is copy it into
                     48:    a buffer. */
                     49: int
                     50: raw_rcv (struct sk_buff *skb, struct device *dev, struct options *opt,
                     51:         unsigned long daddr, unsigned short len, unsigned long saddr,
                     52:         int redo, struct ip_protocol *protocol)
                     53: {
                     54: 
                     55:    volatile struct sock *sk;
                     56: 
                     57:    sk = protocol->data;
                     58:    
                     59:    /* now we need to copy this into memory. */
                     60:    if (!redo )
                     61:      {
                     62:        skb->dev = dev;
                     63:        skb->saddr = daddr;
                     64:        skb->daddr = saddr;
                     65:        /* now see if we are in use. */
                     66:        cli();
                     67:        if (sk->inuse)
                     68:          {
                     69:             PRINTK ("raw_rcv adding to backlog. \n");
                     70:             if (sk->back_log == NULL)
                     71:               {
                     72:                  sk->back_log = skb;
                     73:                  skb->next = skb;
                     74:                  skb->prev = skb;
                     75:               }
                     76:             else
                     77:               {
                     78:                  skb->next = sk->back_log;
                     79:                  skb->prev = sk->back_log->prev;
                     80:                  skb->prev->next = skb;
                     81:                  skb->next->prev = skb;
                     82:               }
                     83:             sti();
                     84:             return (0);
                     85:          }
                     86:        sk->inuse = 1;
                     87:        sti();
                     88:      }
                     89: 
                     90:    skb->sk = sk;
                     91:    skb->len = len;
                     92: 
                     93:    /* charge it too the socket. */
                     94:    if (sk->rmem_alloc + skb->mem_len >= SK_RMEM_MAX)
                     95:      {
                     96:        skb->sk = NULL;
                     97:        free_skb (skb, FREE_READ);
                     98:        return (0);
                     99:      }
                    100:             
                    101:    sk->rmem_alloc += skb->mem_len;
                    102: 
                    103:    /* now just put it onto the queue. */
                    104:    if (sk->rqueue == NULL)
                    105:      {
                    106:        sk->rqueue = skb;
                    107:        skb->next = skb;
                    108:        skb->prev = skb;
                    109:      }
                    110:    else
                    111:      {
                    112:        skb->next = sk->rqueue;
                    113:        skb->prev = sk->rqueue->prev;
                    114:        skb->prev->next = skb;
                    115:        skb->next->prev = skb;
                    116:      }
                    117:    skb->len = len;
                    118:    wake_up (sk->sleep);
                    119:    release_sock (sk);
                    120:    return (0);
                    121: }
                    122: 
                    123: static  int
                    124: raw_loopback (volatile struct sock *sk, int prot, char *from, int len, 
                    125:              unsigned long daddr)
                    126: {
                    127:    /* just pretend it just came in. */
                    128:    struct sk_buff *skb;
                    129:    int err;
                    130:    skb = malloc (len+sizeof (*skb));
                    131:    if (skb == NULL) return (-ENOMEM);
                    132: 
                    133:    skb->mem_addr = skb;
                    134:    skb->mem_len = len + sizeof (*skb);
                    135:    skb->h.raw = (unsigned char *)(skb+1);
                    136:    verify_area (from, len);
                    137:    memcpy_fromfs (skb+1, from, len);
                    138:    err = raw_rcv (skb, NULL, NULL, daddr, len, sk->saddr, prot, 0);
                    139:    return (err);
                    140: }
                    141: 
                    142: /* this will do terrible things if len + ipheader + devheader > dev->mtu */
                    143: static int
                    144: raw_sendto (volatile struct sock *sk, unsigned char *from, int len,
                    145:            int noblock,
                    146:            unsigned flags, struct sockaddr_in *usin, int addr_len)
                    147: {
                    148:    struct sk_buff *skb;
                    149:    struct device *dev=NULL;
                    150:    struct sockaddr_in sin;
                    151:    int tmp;
                    152: 
                    153:    /* check the flags. */
                    154:    if (flags) return (-EINVAL);
                    155:    if (len < 0) return (-EINVAL);
                    156: 
                    157:    /* get and verify the address. */
                    158:    if (usin)
                    159:      {
                    160:        if (addr_len < sizeof (sin))
                    161:          return (-EINVAL);
                    162:        verify_area (usin, sizeof (sin));
                    163:        memcpy_fromfs (&sin, usin, sizeof(sin));
                    164:        if (sin.sin_family &&
                    165:            sin.sin_family != AF_INET)
                    166:          return (-EINVAL);
                    167:      }
                    168:    else
                    169:      {
                    170:        if (sk->state != TCP_ESTABLISHED)
                    171:          return (-EINVAL);
                    172:        sin.sin_family = AF_INET;
                    173:        sin.sin_port = sk->protocol;
                    174:        sin.sin_addr.s_addr = sk->daddr;
                    175:      }
                    176:    if (sin.sin_port == 0) sin.sin_port = sk->protocol;
                    177: 
                    178:    if ((sin.sin_addr.s_addr & 0xff000000) == 0)
                    179:      {
                    180:        int err;
                    181:        err = raw_loopback (sk, sin.sin_port, from,  len,
                    182:                            sin.sin_addr.s_addr);
                    183:        if (err < 0) return (err);
                    184:      }
                    185: 
                    186:    sk->inuse = 1;
                    187:    skb = sk->prot->wmalloc (sk, len+sizeof (*skb) + sk->prot->max_header, 0);
                    188:    /* this shouldn't happen, but it could. */
                    189:    if (skb == NULL)
                    190:      {
                    191:        PRINTK ("raw_sendto: write buffer full?\n");
                    192:        print_sk (sk);
                    193:        release_sock (sk);
                    194:        return (-EAGAIN);
                    195:      }
                    196:    skb->mem_addr = skb;
                    197:    skb->mem_len = len + sizeof (*skb) +sk->prot->max_header;
                    198:    skb->sk = sk;
                    199:    skb->free = 1; /* these two should be unecessary. */
                    200:    skb->arp = 0;
                    201:    tmp = sk->prot->build_header (skb, sk->saddr, 
                    202:                                 sin.sin_addr.s_addr, &dev,
                    203:                                 sk->protocol, sk->opt, skb->mem_len);
                    204:    if (tmp < 0)
                    205:      {
                    206:        sk->prot->wfree (sk, skb->mem_addr, skb->mem_len);
                    207:        release_sock (sk);
                    208:        return (tmp);
                    209:      }
                    210:    verify_area (from, len);
                    211:    memcpy_fromfs (skb+1, from, len);
                    212:    skb->len = tmp + len;
                    213:    sk->prot->queue_xmit (sk, dev, skb, 1);
                    214:    return (len);
                    215: }
                    216: 
                    217: static int
                    218: raw_write (volatile struct sock *sk, unsigned char *buff, int len, int noblock,
                    219:           unsigned flags)
                    220: {
                    221:    return (raw_sendto (sk, buff, len, noblock, flags, NULL, 0));
                    222: }
                    223: 
                    224: static void
                    225: raw_close (volatile struct sock *sk, int timeout)
                    226: {
                    227:    sk->inuse = 1;
                    228:    sk->state = TCP_CLOSE;
                    229:    delete_ip_protocol ((struct ip_protocol *)sk->pair);
                    230:    free_s ((void *)sk->pair, sizeof (struct ip_protocol));
                    231:    release_sock (sk);
                    232: }
                    233: 
                    234: static int
                    235: raw_init (volatile struct sock *sk)
                    236: {
                    237:    struct ip_protocol *p;
                    238:    p = malloc (sizeof (*p));
                    239:    if (p == NULL) return (-ENOMEM);
                    240: 
                    241:    p->handler = raw_rcv;
                    242:    p->protocol = sk->protocol;
                    243:    p->data = (void *)sk;
                    244:    add_ip_protocol (p);
                    245:    
                    246:    /* we need to remember this somewhere. */
                    247:    sk->pair = (volatile struct sock *)p;
                    248: 
                    249:    return (0);
                    250: }
                    251: 
                    252: 
                    253: int
                    254: raw_recvfrom (volatile struct sock *sk, unsigned char *to, int len,
                    255:              int noblock,
                    256:              unsigned flags, struct sockaddr_in *sin, int *addr_len)
                    257: {
                    258:        /* this should be easy, if there is something there we
                    259:           return it, otherwise we block. */
                    260:        int copied=0;
                    261:        struct sk_buff *skb;
                    262:        if (len == 0) return (0);
                    263:        if (len < 0) return (-EINVAL);
                    264:        if (addr_len)
                    265:          {
                    266:                  verify_area (addr_len, sizeof(*addr_len));
                    267:                  put_fs_long (sizeof (*sin), addr_len);
                    268:          }
                    269:        sk->inuse = 1;
                    270:        while (sk->rqueue == NULL)
                    271:          {
                    272:             if (noblock)
                    273:               {
                    274:                  release_sock (sk);
                    275:                  return (-EAGAIN);
                    276:               }
                    277:             release_sock (sk);
                    278:             cli();
                    279:             if (sk->rqueue == NULL)
                    280:               {
                    281:                  interruptible_sleep_on (sk->sleep);
                    282:                  if (current->signal & ~current->blocked)
                    283:                    {
                    284:                       return (-ERESTARTSYS);
                    285:                    }
                    286:               }
                    287:             sti();
                    288:          }
                    289:        skb = sk->rqueue;
                    290: 
                    291:        if (!(flags & MSG_PEEK))
                    292:          {
                    293:                  if (skb->next == skb )
                    294:                    {
                    295:                            sk->rqueue = NULL;
                    296:                    }
                    297:                  else
                    298:                    {
                    299:                            sk->rqueue = sk->rqueue ->next;
                    300:                            skb->prev->next = skb->next;
                    301:                            skb->next->prev = skb->prev;
                    302:                    }
                    303:          }
                    304:        copied = min (len, skb->len);
                    305:        verify_area (to, copied);
                    306:        memcpy_tofs (to, skb->h.raw,  copied);
                    307:        /* copy the address. */
                    308:        if (sin)
                    309:          {
                    310:                  struct sockaddr_in addr;
                    311:                  addr.sin_family = AF_INET;
                    312:                  addr.sin_addr.s_addr = skb->daddr;
                    313:                  verify_area (sin, sizeof (*sin));
                    314:                  memcpy_tofs(sin, &addr, sizeof (*sin));
                    315:          }
                    316: 
                    317:        if (!(flags & MSG_PEEK))
                    318:          {
                    319:             free_skb (skb, FREE_READ);
                    320:          }
                    321:        release_sock (sk);
                    322:        return (copied);
                    323: 
                    324: }
                    325: 
                    326: int
                    327: raw_read (volatile struct sock *sk, unsigned char *buff, int len, int noblock,
                    328:          unsigned flags)
                    329: {
                    330:        return (raw_recvfrom (sk, buff, len, noblock, flags, NULL, NULL));
                    331: }
                    332: 
                    333: 
                    334: int udp_connect (volatile struct sock *sk, struct sockaddr_in *usin,
                    335:                 int addr_len);
                    336: 
                    337: int udp_select (volatile struct sock *sk, int sel_type, select_table *wait);
                    338: 
                    339: 
                    340: struct proto raw_prot =
                    341: {
                    342:   sock_wmalloc,
                    343:   sock_rmalloc,
                    344:   sock_wfree,
                    345:   sock_rfree,
                    346:   sock_rspace,
                    347:   sock_wspace,
                    348:   raw_close,
                    349:   raw_read,
                    350:   raw_write,
                    351:   raw_sendto,
                    352:   raw_recvfrom,
                    353:   ip_build_header,
                    354:   udp_connect,
                    355:   NULL,
                    356:   ip_queue_xmit,
                    357:   ip_retransmit,
                    358:   NULL,
                    359:   NULL,
                    360:   raw_rcv,
                    361:   udp_select,
                    362:   NULL,
                    363:   raw_init,
                    364:   128,
                    365:   0,
                    366:   {NULL,}
                    367: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.