Annotation of linux/net/tcp/raw.c, revision 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.