root/net/inet/packet.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. min
  2. packet_rcv
  3. packet_sendto
  4. packet_write
  5. packet_close
  6. packet_init
  7. packet_recvfrom
  8. packet_read

   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  *              PACKET - implements raw packet sockets.
   7  *
   8  * Version:     @(#)packet.c    1.28    20/12/93
   9  *
  10  * Authors:     Ross Biro, <bir7@leland.Stanford.Edu>
  11  *              Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  12  *
  13  * Fixes:       
  14  *              Alan Cox        :       verify_area() now used correctly
  15  *              Alan Cox        :       new skbuff lists, look ma no backlogs!
  16  *              Alan Cox        :       tidied skbuff lists.
  17  *              Alan Cox        :       Now uses generic datagram routines I
  18  *                                      added. Also fixed the peek/read crash
  19  *                                      from all old Linux datagram code.
  20  *              Alan Cox        :       Uses the improved datagram code.
  21  *              Alan Cox        :       Clean up for final release.
  22  *
  23  *
  24  *              This program is free software; you can redistribute it and/or
  25  *              modify it under the terms of the GNU General Public License
  26  *              as published by the Free Software Foundation; either version
  27  *              2 of the License, or (at your option) any later version.
  28  */
  29 #include <linux/types.h>
  30 #include <linux/sched.h>
  31 #include <linux/fcntl.h>
  32 #include <linux/socket.h>
  33 #include <linux/in.h>
  34 #include "inet.h"
  35 #include "devinet.h"
  36 #include "ip.h"
  37 #include "protocol.h"
  38 #include "tcp.h"
  39 #include "skbuff.h"
  40 #include "sockinet.h"
  41 #include <linux/errno.h>
  42 #include <linux/timer.h>
  43 #include <asm/system.h>
  44 #include <asm/segment.h>
  45 #include "udp.h"
  46 #include "raw.h"
  47 
  48 /*
  49  *      I'm sure there should be one of these, not one every file.
  50  */
  51 
  52 static unsigned long min(unsigned long a, unsigned long b)
     /* [previous][next][first][last][top][bottom][index][help] */
  53 {
  54         if (a < b) 
  55                 return(a);
  56         return(b);
  57 }
  58 
  59 
  60 /* 
  61  *      This should be the easiest of all, all we do is copy it into a buffer. 
  62  */
  63  
  64 int packet_rcv(struct sk_buff *skb, struct device *dev,  struct packet_type *pt)
     /* [previous][next][first][last][top][bottom][index][help] */
  65 {
  66         struct sock *sk;
  67 
  68         sk = (struct sock *) pt->data;
  69         skb->dev = dev;
  70         skb->len += dev->hard_header_len;
  71 
  72         skb->sk = sk;
  73 
  74         /* Charge it too the socket. */
  75         if (sk->rmem_alloc + skb->mem_len >= sk->rcvbuf) 
  76         {
  77                 skb->sk = NULL;
  78                 kfree_skb(skb, FREE_READ);
  79                 return(0);
  80         }
  81         sk->rmem_alloc += skb->mem_len;
  82         skb_queue_tail(&sk->rqueue,skb);
  83         release_sock(sk);
  84         sk->data_ready(sk,skb->len);    
  85         return(0);
  86 }
  87 
  88 
  89 /*
  90  *      This will do terrible things if len + ipheader + devheader > dev->mtu 
  91  *      Since only root can use these thats okish...
  92  */
  93  
  94 static int packet_sendto(struct sock *sk, unsigned char *from, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
  95               int noblock, unsigned flags, struct sockaddr_in *usin,
  96               int addr_len)
  97 {
  98         struct sk_buff *skb;
  99         struct device *dev;
 100         struct sockaddr saddr;
 101         int err;
 102 
 103         /* Check the flags. */
 104         if (flags) 
 105                 return(-EINVAL);
 106         if (len < 0) 
 107                 return(-EINVAL);
 108         
 109         /* Get and verify the address. */
 110         if (usin) 
 111         {
 112                 if (addr_len < sizeof(saddr)) 
 113                         return(-EINVAL);
 114                 err=verify_area(VERIFY_READ, usin, sizeof(saddr));
 115                 if(err)
 116                         return err;
 117                 memcpy_fromfs(&saddr, usin, sizeof(saddr));
 118         } 
 119         else
 120                 return(-EINVAL);
 121         
 122         err=verify_area(VERIFY_READ,from,len);
 123         if(err)
 124                 return(err);
 125         /* Find the device first to size check it */
 126 
 127         saddr.sa_data[13] = 0;
 128         dev = dev_get(saddr.sa_data);
 129         if (dev == NULL) 
 130         {
 131                 return(-ENXIO);
 132         }
 133         if(len>dev->mtu)
 134                 return -EMSGSIZE;
 135 
 136         /* Now allocate the buffer, knowing 4K pagelimits wont break this line */  
 137         skb = (struct sk_buff *) sk->prot->wmalloc(sk, len+sizeof(*skb), 0, GFP_KERNEL);
 138 
 139         /* This shouldn't happen, but it could. */
 140         if (skb == NULL) 
 141         {
 142                 DPRINTF((DBG_PKT, "packet_sendto: write buffer full?\n"));
 143                 return(-ENOMEM);
 144         }
 145         /* Fill it in */
 146         skb->sk = sk;
 147         skb->free = 1;
 148         memcpy_fromfs (skb+1, from, len);
 149         skb->len = len;
 150         skb->next = NULL;
 151         if (dev->flags & IFF_UP) 
 152                 dev->queue_xmit(skb, dev, sk->priority);
 153         else 
 154                 kfree_skb(skb, FREE_WRITE);
 155         return(len);
 156 }
 157 
 158 
 159 static int packet_write(struct sock *sk, unsigned char *buff, 
     /* [previous][next][first][last][top][bottom][index][help] */
 160              int len, int noblock,  unsigned flags)
 161 {
 162         return(packet_sendto(sk, buff, len, noblock, flags, NULL, 0));
 163 }
 164 
 165 
 166 static void packet_close(struct sock *sk, int timeout)
     /* [previous][next][first][last][top][bottom][index][help] */
 167 {
 168         sk->inuse = 1;
 169         sk->state = TCP_CLOSE;
 170         dev_remove_pack((struct packet_type *)sk->pair);
 171         kfree_s((void *)sk->pair, sizeof(struct packet_type));
 172         sk->pair = NULL;
 173         release_sock(sk);
 174 }
 175 
 176 
 177 static int packet_init(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 178 {
 179         struct packet_type *p;
 180 
 181         p = (struct packet_type *) kmalloc(sizeof(*p), GFP_KERNEL);
 182         if (p == NULL) 
 183                 return(-ENOMEM);
 184 
 185         p->func = packet_rcv;
 186         p->type = sk->num;
 187         p->data = (void *)sk;
 188         dev_add_pack(p);
 189          
 190         /* We need to remember this somewhere. */
 191         sk->pair = (struct sock *)p;
 192 
 193         return(0);
 194 }
 195 
 196 
 197 /*
 198  * This should be easy, if there is something there
 199  * we return it, otherwise we block.
 200  */
 201 int packet_recvfrom(struct sock *sk, unsigned char *to, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 202                 int noblock, unsigned flags, struct sockaddr_in *sin,
 203                 int *addr_len)
 204 {
 205         int copied=0;
 206         struct sk_buff *skb;
 207         struct sockaddr *saddr;
 208         int err;
 209         
 210         saddr = (struct sockaddr *)sin;
 211         if (len == 0) 
 212                 return(0);
 213         if (len < 0) 
 214                 return(-EINVAL);
 215 
 216         if (sk->shutdown & RCV_SHUTDOWN) 
 217                 return(0);
 218         if (addr_len) 
 219         {
 220                 err=verify_area(VERIFY_WRITE, addr_len, sizeof(*addr_len));
 221                 if(err)
 222                         return err;
 223                 put_fs_long(sizeof(*saddr), addr_len);
 224         }
 225   
 226         err=verify_area(VERIFY_WRITE,to,len);
 227         if(err)
 228                 return err;
 229         skb=skb_recv_datagram(sk,flags,noblock,&err);
 230         if(skb==NULL)
 231                 return err;
 232         copied = min(len, skb->len);
 233 
 234         memcpy_tofs(to, skb+1, copied); /* Don't use skb_copy_datagram here: We can't get frag chains */
 235 
 236         /* Copy the address. */
 237         if (saddr) 
 238         {
 239                 struct sockaddr addr;
 240 
 241                 addr.sa_family = skb->dev->type;
 242                 memcpy(addr.sa_data,skb->dev->name, 14);
 243                 verify_area(VERIFY_WRITE, saddr, sizeof(*saddr));
 244                 memcpy_tofs(saddr, &addr, sizeof(*saddr));
 245         }
 246 
 247         skb_free_datagram(skb);         /* Its either been used up, or its a peek_copy anyway */
 248 
 249         release_sock(sk);
 250         return(copied);
 251 }
 252 
 253 
 254 int packet_read(struct sock *sk, unsigned char *buff,
     /* [previous][next][first][last][top][bottom][index][help] */
 255             int len, int noblock, unsigned flags)
 256 {
 257         return(packet_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
 258 }
 259 
 260 
 261 struct proto packet_prot = 
 262 {
 263         sock_wmalloc,
 264         sock_rmalloc,
 265         sock_wfree,
 266         sock_rfree,
 267         sock_rspace,
 268         sock_wspace,
 269         packet_close,
 270         packet_read,
 271         packet_write,
 272         packet_sendto,
 273         packet_recvfrom,
 274         ip_build_header,
 275         udp_connect,
 276         NULL,
 277         ip_queue_xmit,
 278         ip_retransmit,
 279         NULL,
 280         NULL,
 281         NULL, 
 282         datagram_select,
 283         NULL,
 284         packet_init,
 285         NULL,
 286         NULL,   /* No set/get socket options */
 287         NULL,
 288         128,
 289         0,
 290         {NULL,},
 291         "PACKET"
 292 };

/* [previous][next][first][last][top][bottom][index][help] */