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

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