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

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